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