]> git.pld-linux.org Git - packages/openssh.git/blame - openssh-5.8p1-authorized-keys-command.patch
- release 2 (by relup.sh)
[packages/openssh.git] / openssh-5.8p1-authorized-keys-command.patch
CommitLineData
108bb9ae
ER
1diff -up openssh-5.8p1/auth2-pubkey.c.akc openssh-5.8p1/auth2-pubkey.c
2--- openssh-5.8p1/auth2-pubkey.c.akc 2011-02-10 13:21:27.000000000 +0100
3+++ openssh-5.8p1/auth2-pubkey.c 2011-02-10 13:21:28.000000000 +0100
4@@ -27,6 +27,7 @@
5
6 #include <sys/types.h>
7 #include <sys/stat.h>
8+#include <sys/wait.h>
9
10 #include <fcntl.h>
11 #include <pwd.h>
12@@ -268,27 +269,15 @@ match_principals_file(char *file, struct
13
14 /* return 1 if user allows given key */
15 static int
16-user_key_allowed2(struct passwd *pw, Key *key, char *file)
17+user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw)
18 {
19 char line[SSH_MAX_PUBKEY_BYTES];
20 const char *reason;
21 int found_key = 0;
22- FILE *f;
23 u_long linenum = 0;
24 Key *found;
25 char *fp;
26
27- /* Temporarily use the user's uid. */
28- temporarily_use_uid(pw);
29-
30- debug("trying public key file %s", file);
31- f = auth_openkeyfile(file, pw, options.strict_modes);
32-
33- if (!f) {
34- restore_uid();
35- return 0;
36- }
37-
38 found_key = 0;
39 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
40
41@@ -381,8 +370,6 @@ user_key_allowed2(struct passwd *pw, Key
42 break;
43 }
44 }
45- restore_uid();
46- fclose(f);
47 key_free(found);
48 if (!found_key)
49 debug2("key not found");
50@@ -444,13 +431,191 @@ user_cert_trusted_ca(struct passwd *pw,
51 return ret;
52 }
53
54-/* check whether given key is in .ssh/authorized_keys* */
55+/* return 1 if user allows given key */
56+static int
57+user_key_allowed2(struct passwd *pw, Key *key, char *file)
58+{
59+ FILE *f;
60+ int found_key = 0;
61+
62+ /* Temporarily use the user's uid. */
63+ temporarily_use_uid(pw);
64+
65+ debug("trying public key file %s", file);
66+ f = auth_openkeyfile(file, pw, options.strict_modes);
67+
68+ if (f) {
69+ found_key = user_search_key_in_file (f, file, key, pw);
70+ fclose(f);
71+ }
72+
73+ restore_uid();
74+ return found_key;
75+}
76+
77+#ifdef WITH_AUTHORIZED_KEYS_COMMAND
78+
79+#define WHITESPACE " \t\r\n"
80+
81+/* return 1 if user allows given key */
82+static int
83+user_key_via_command_allowed2(struct passwd *pw, Key *key)
84+{
85+ FILE *f;
86+ int found_key = 0;
87+ char *progname = NULL;
88+ char *cp;
89+ struct passwd *runas_pw;
90+ struct stat st;
91+ int childdescriptors[2], i;
92+ pid_t pstat, pid, child;
93+
94+ if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/')
95+ return -1;
96+
97+ /* get the run as identity from config */
98+ runas_pw = (options.authorized_keys_command_runas == NULL)? pw
99+ : getpwnam (options.authorized_keys_command_runas);
100+ if (!runas_pw) {
101+ error("%s: getpwnam(\"%s\"): %s", __func__,
102+ options.authorized_keys_command_runas, strerror(errno));
103+ return 0;
104+ }
105+
106+ /* Temporarily use the specified uid. */
107+ if (runas_pw->pw_uid != 0)
108+ temporarily_use_uid(runas_pw);
109+
110+ progname = xstrdup(options.authorized_keys_command);
111+
112+ debug3("%s: checking program '%s'", __func__, progname);
113+
114+ if (stat (progname, &st) < 0) {
115+ error("%s: stat(\"%s\"): %s", __func__,
116+ progname, strerror(errno));
117+ goto go_away;
118+ }
119+
120+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
121+ error("bad ownership or modes for AuthorizedKeysCommand \"%s\"",
122+ progname);
123+ goto go_away;
124+ }
125+
126+ if (!S_ISREG(st.st_mode)) {
127+ error("AuthorizedKeysCommand \"%s\" is not a regular file",
128+ progname);
129+ goto go_away;
130+ }
131+
132+ /*
133+ * Descend the path, checking that each component is a
134+ * root-owned directory with strict permissions.
135+ */
136+ do {
137+ if ((cp = strrchr(progname, '/')) == NULL)
138+ break;
139+ else
140+ *cp = '\0';
141+
142+ debug3("%s: checking component '%s'", __func__, (*progname == '\0' ? "/" : progname));
143+
144+ if (stat((*progname == '\0' ? "/" : progname), &st) != 0) {
145+ error("%s: stat(\"%s\"): %s", __func__,
146+ progname, strerror(errno));
147+ goto go_away;
148+ }
149+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
150+ error("bad ownership or modes for AuthorizedKeysCommand path component \"%s\"",
151+ progname);
152+ goto go_away;
153+ }
154+ if (!S_ISDIR(st.st_mode)) {
155+ error("AuthorizedKeysCommand path component \"%s\" is not a directory",
156+ progname);
157+ goto go_away;
158+ }
159+ } while (1);
160+
161+ /* open the pipe and read the keys */
162+ if (pipe(childdescriptors)) {
163+ error("failed to pipe(2) for AuthorizedKeysCommand: %s",
164+ strerror(errno));
165+ goto go_away;
166+ }
167+
168+ child = fork();
169+ if (child == -1) {
170+ error("failed to fork(2) for AuthorizedKeysCommand: %s",
171+ strerror(errno));
172+ goto go_away;
173+ } else if (child == 0) {
174+ /* we're in the child process here -- we should never return from this block. */
175+ /* permanently drop privs in child process */
176+ if (runas_pw->pw_uid != 0) {
177+ restore_uid();
178+ permanently_set_uid(runas_pw);
179+ }
180+
181+ close(childdescriptors[0]);
182+ /* put the write end of the pipe on stdout (FD 1) */
183+ if (dup2(childdescriptors[1], 1) == -1) {
184+ error("failed to dup2(2) from AuthorizedKeysCommand: %s",
185+ strerror(errno));
186+ _exit(127);
187+ }
188+
189+ debug3("about to execl() AuthorizedKeysCommand: \"%s\" \"%s\"", options.authorized_keys_command, pw->pw_name);
190+ /* see session.c:child_close_fds() */
191+ for (i = 3; i < 64; ++i) {
192+ close(i);
193+ }
194+
195+ execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL);
196+
197+ /* if we got here, it didn't work */
198+ error("failed to execl AuthorizedKeysCommand: %s", strerror(errno)); /* this won't work because we closed the fds above */
199+ _exit(127);
200+ }
201+
202+ close(childdescriptors[1]);
203+ f = fdopen(childdescriptors[0], "r");
204+ if (!f) {
205+ error("%s: could not buffer FDs from AuthorizedKeysCommand (\"%s\", \"r\"): %s", __func__,
206+ options.authorized_keys_command, strerror (errno));
207+ goto go_away;
208+ }
209+
210+ found_key = user_search_key_in_file (f, options.authorized_keys_command, key, pw);
211+ fclose (f);
212+ do {
213+ pid = waitpid(child, &pstat, 0);
214+ } while (pid == -1 && errno == EINTR);
215+
216+ /* what about the return value from the child process? */
217+go_away:
218+ if (progname)
0fab2cab 219+ free (progname);
108bb9ae
ER
220+
221+ if (runas_pw->pw_uid != 0)
222+ restore_uid();
223+ return found_key;
224+}
225+#endif
226+
227+/* check whether given key is in <AuthorizedKeysCommand or .ssh/authorized_keys* */
228 int
229 user_key_allowed(struct passwd *pw, Key *key)
230 {
231 int success;
232 char *file;
233
234+#ifdef WITH_AUTHORIZED_KEYS_COMMAND
235+ success = user_key_via_command_allowed2(pw, key);
236+ if (success > 0)
237+ return success;
238+#endif
239+
240 if (auth_key_is_revoked(key))
241 return 0;
242 if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
243diff -up openssh-5.8p1/configure.ac.akc openssh-5.8p1/configure.ac
244--- openssh-5.8p1/configure.ac.akc 2011-02-10 13:21:28.000000000 +0100
245+++ openssh-5.8p1/configure.ac 2011-02-10 13:21:28.000000000 +0100
246@@ -1422,6 +1422,18 @@ AC_ARG_WITH(audit,
247 esac ]
248 )
249
250+# Check whether user wants AuthorizedKeysCommand support
251+AKC_MSG="no"
252+AC_ARG_WITH(authorized-keys-command,
253+ [ --with-authorized-keys-command Enable AuthorizedKeysCommand support],
254+ [
255+ if test "x$withval" != "xno" ; then
256+ AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support])
257+ AKC_MSG="yes"
258+ fi
259+ ]
260+)
261+
262 dnl Checks for library functions. Please keep in alphabetical order
263 AC_CHECK_FUNCS( \
264 arc4random \
265@@ -4325,6 +4337,7 @@ echo " SELinux support
266 echo " Smartcard support: $SCARD_MSG"
267 echo " S/KEY support: $SKEY_MSG"
268 echo " TCP Wrappers support: $TCPW_MSG"
269+echo " AuthorizedKeysCommand support: $AKC_MSG"
270 echo " MD5 password support: $MD5_MSG"
271 echo " libedit support: $LIBEDIT_MSG"
272 echo " Solaris process contract support: $SPC_MSG"
273diff -up openssh-5.8p1/servconf.c.akc openssh-5.8p1/servconf.c
274--- openssh-5.8p1/servconf.c.akc 2011-02-10 13:21:28.000000000 +0100
275+++ openssh-5.8p1/servconf.c 2011-02-10 13:28:21.000000000 +0100
276@@ -134,6 +134,8 @@ initialize_server_options(ServerOptions
277 options->num_permitted_opens = -1;
278 options->adm_forced_command = NULL;
279 options->chroot_directory = NULL;
280+ options->authorized_keys_command = NULL;
281+ options->authorized_keys_command_runas = NULL;
282 options->zero_knowledge_password_authentication = -1;
283 options->revoked_keys_file = NULL;
284 options->trusted_user_ca_keys = NULL;
285@@ -331,6 +333,7 @@ typedef enum {
286 sZeroKnowledgePasswordAuthentication, sHostCertificate,
287 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
288 sKexAlgorithms, sIPQoS,
289+ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs,
290 sDeprecated, sUnsupported
291 } ServerOpCodes;
292
293@@ -456,6 +459,13 @@ static struct {
294 { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
295 { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
296 { "ipqos", sIPQoS, SSHCFG_ALL },
297+#ifdef WITH_AUTHORIZED_KEYS_COMMAND
298+ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
299+ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandRunAs, SSHCFG_ALL },
300+#else
301+ { "authorizedkeyscommand", sUnsupported, SSHCFG_ALL },
302+ { "authorizedkeyscommandrunas", sUnsupported, SSHCFG_ALL },
303+#endif
304 { NULL, sBadOption, 0 }
305 };
306
307@@ -1406,6 +1416,20 @@ process_server_config_line(ServerOptions
308 }
309 break;
310
311+ case sAuthorizedKeysCommand:
312+ len = strspn(cp, WHITESPACE);
313+ if (*activep && options->authorized_keys_command == NULL)
314+ options->authorized_keys_command = xstrdup(cp + len);
315+ return 0;
316+
317+ case sAuthorizedKeysCommandRunAs:
318+ charptr = &options->authorized_keys_command_runas;
319+
320+ arg = strdelim(&cp);
321+ if (*activep && *charptr == NULL)
322+ *charptr = xstrdup(arg);
323+ break;
324+
325 case sDeprecated:
326 logit("%s line %d: Deprecated option %s",
327 filename, linenum, arg);
328@@ -1499,6 +1523,8 @@ copy_set_server_options(ServerOptions *d
329 M_CP_INTOPT(gss_authentication);
330 M_CP_INTOPT(rsa_authentication);
331 M_CP_INTOPT(pubkey_authentication);
332+ M_CP_STROPT(authorized_keys_command);
333+ M_CP_STROPT(authorized_keys_command_runas);
334 M_CP_INTOPT(kerberos_authentication);
335 M_CP_INTOPT(hostbased_authentication);
336 M_CP_INTOPT(hostbased_uses_name_from_packet_only);
337@@ -1753,6 +1779,8 @@ dump_config(ServerOptions *o)
338 dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
339 dump_cfg_string(sAuthorizedPrincipalsFile,
340 o->authorized_principals_file);
341+ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
342+ dump_cfg_string(sAuthorizedKeysCommandRunAs, o->authorized_keys_command_runas);
343
344 /* string arguments requiring a lookup */
345 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
346diff -up openssh-5.8p1/servconf.h.akc openssh-5.8p1/servconf.h
347--- openssh-5.8p1/servconf.h.akc 2011-02-10 13:21:28.000000000 +0100
348+++ openssh-5.8p1/servconf.h 2011-02-10 13:21:28.000000000 +0100
349@@ -161,6 +161,8 @@ typedef struct {
350 char *revoked_keys_file;
351 char *trusted_user_ca_keys;
352 char *authorized_principals_file;
353+ char *authorized_keys_command;
354+ char *authorized_keys_command_runas;
355 } ServerOptions;
356
357 void initialize_server_options(ServerOptions *);
358diff -up openssh-5.8p1/sshd_config.0.akc openssh-5.8p1/sshd_config.0
359--- openssh-5.8p1/sshd_config.0.akc 2011-02-10 13:21:28.000000000 +0100
360+++ openssh-5.8p1/sshd_config.0 2011-02-10 13:21:28.000000000 +0100
361@@ -71,6 +71,23 @@ DESCRIPTION
362
363 See PATTERNS in ssh_config(5) for more information on patterns.
364
365+ AuthorizedKeysCommand
366+
367+ Specifies a program to be used for lookup of the user's
368+ public keys. The program will be invoked with its first
369+ argument the name of the user being authorized, and should produce
370+ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS
371+ in sshd(8)). By default (or when set to the empty string) there is no
372+ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully
373+ authorize the user, authorization falls through to the
374+ AuthorizedKeysFile. Note that this option has an effect
375+ only with PubkeyAuthentication turned on.
376+
377+ AuthorizedKeysCommandRunAs
378+ Specifies the user under whose account the AuthorizedKeysCommand is run.
379+ Empty string (the default value) means the user being authorized
380+ is used.
381+
382 AuthorizedKeysFile
383 Specifies the file that contains the public keys that can be used
384 for user authentication. The format is described in the
385@@ -398,7 +415,8 @@ DESCRIPTION
386
387 Only a subset of keywords may be used on the lines following a
388 Match keyword. Available keywords are AllowAgentForwarding,
389- AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile,
390+ AllowTcpForwarding, AuthorizedKeysFile, AuthorizedKeysCommand,
391+ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile,
392 Banner, ChrootDirectory, ForceCommand, GatewayPorts,
393 GSSAPIAuthentication, HostbasedAuthentication,
394 HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
395diff -up openssh-5.8p1/sshd_config.5.akc openssh-5.8p1/sshd_config.5
396--- openssh-5.8p1/sshd_config.5.akc 2011-02-10 13:21:28.000000000 +0100
397+++ openssh-5.8p1/sshd_config.5 2011-02-10 13:21:28.000000000 +0100
398@@ -703,6 +703,8 @@ Available keywords are
399 .Cm AllowAgentForwarding ,
400 .Cm AllowTcpForwarding ,
401 .Cm AuthorizedKeysFile ,
402+.Cm AuthorizedKeysCommand ,
403+.Cm AuthorizedKeysCommandRunAs ,
404 .Cm AuthorizedPrincipalsFile ,
405 .Cm Banner ,
406 .Cm ChrootDirectory ,
407@@ -715,6 +717,7 @@ Available keywords are
408 .Cm KerberosAuthentication ,
409 .Cm MaxAuthTries ,
410 .Cm MaxSessions ,
411+.Cm PubkeyAuthentication ,
412 .Cm PasswordAuthentication ,
413 .Cm PermitEmptyPasswords ,
414 .Cm PermitOpen ,
415@@ -917,6 +920,20 @@ Specifies a list of revoked public keys.
416 Keys listed in this file will be refused for public key authentication.
417 Note that if this file is not readable, then public key authentication will
418 be refused for all users.
419+.It Cm AuthorizedKeysCommand
420+Specifies a program to be used for lookup of the user's
421+public keys. The program will be invoked with its first
422+argument the name of the user being authorized, and should produce
423+on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS
424+in sshd(8)). By default (or when set to the empty string) there is no
425+AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully
426+authorize the user, authorization falls through to the
427+AuthorizedKeysFile. Note that this option has an effect
428+only with PubkeyAuthentication turned on.
429+.It Cm AuthorizedKeysCommandRunAs
430+Specifies the user under whose account the AuthorizedKeysCommand is run. Empty
431+string (the default value) means the user being authorized is used.
432+.Dq
433 .It Cm RhostsRSAAuthentication
434 Specifies whether rhosts or /etc/hosts.equiv authentication together
435 with successful RSA host authentication is allowed.
436diff -up openssh-5.8p1/sshd_config.akc openssh-5.8p1/sshd_config
437--- openssh-5.8p1/sshd_config.akc 2011-02-10 13:21:28.000000000 +0100
438+++ openssh-5.8p1/sshd_config 2011-02-10 13:21:28.000000000 +0100
439@@ -46,6 +46,8 @@ SyslogFacility AUTHPRIV
440 #RSAAuthentication yes
441 #PubkeyAuthentication yes
442 #AuthorizedKeysFile .ssh/authorized_keys
443+#AuthorizedKeysCommand none
444+#AuthorizedKeysCommandRunAs nobody
445
446 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
447 #RhostsRSAAuthentication no
This page took 0.123926 seconds and 4 git commands to generate.