]> git.pld-linux.org Git - packages/openssh.git/blob - authorized-keys-command.patch
- fix ssh-ldap-helper path
[packages/openssh.git] / authorized-keys-command.patch
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.076682 seconds and 3 git commands to generate.