1 /*
2  * ProFTPD - FTP server daemon
3  * Copyright (c) 1997, 1998 Public Flood Software
4  * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
5  * Copyright (c) 2001-2020 The ProFTPD Project team
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20  *
21  * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
22  * and other respective copyright holders give permission to link this program
23  * with OpenSSL, and distribute the resulting executable, without including
24  * the source code for OpenSSL in the source distribution.
25  */
26 
27 /* Authentication front-end for ProFTPD. */
28 
29 #include "conf.h"
30 #include "privs.h"
31 #include "error.h"
32 #include "openbsd-blowfish.h"
33 
34 static pool *auth_pool = NULL;
35 static size_t auth_max_passwd_len = PR_TUNABLE_PASSWORD_MAX;
36 static pr_table_t *auth_tab = NULL, *uid_tab = NULL, *user_tab = NULL,
37   *gid_tab = NULL, *group_tab = NULL;
38 static xaset_t *auth_module_list = NULL;
39 
40 struct auth_module_elt {
41   struct auth_module_elt *prev, *next;
42   const char *name;
43 };
44 
45 static const char *trace_channel = "auth";
46 
47 /* Caching of ID-to-name lookups, for both UIDs and GIDs, is enabled by
48  * default.
49  */
50 static unsigned int auth_caching = PR_AUTH_CACHE_FL_DEFAULT;
51 
52 /* Key comparison callback for the uidcache and gidcache. */
uid_keycmp_cb(const void * key1,size_t keysz1,const void * key2,size_t keysz2)53 static int uid_keycmp_cb(const void *key1, size_t keysz1,
54     const void *key2, size_t keysz2) {
55 
56   /* Return zero to indicate a match, non-zero otherwise. */
57   return (*((uid_t *) key1) == *((uid_t *) key2) ? 0 : 1);
58 }
59 
gid_keycmp_cb(const void * key1,size_t keysz1,const void * key2,size_t keysz2)60 static int gid_keycmp_cb(const void *key1, size_t keysz1,
61     const void *key2, size_t keysz2) {
62 
63   /* Return zero to indicate a match, non-zero otherwise. */
64   return (*((gid_t *) key1) == *((gid_t *) key2) ? 0 : 1);
65 }
66 
67 /* Key "hash" callback for the uidcache and gidcache. */
uid_hash_cb(const void * key,size_t keysz)68 static unsigned int uid_hash_cb(const void *key, size_t keysz) {
69   uid_t u;
70   unsigned int res;
71 
72   memcpy(&u, key, keysz);
73   res = (unsigned int) (u << 8);
74 
75   return res;
76 }
77 
gid_hash_cb(const void * key,size_t keysz)78 static unsigned int gid_hash_cb(const void *key, size_t keysz) {
79   gid_t g;
80   unsigned int res;
81 
82   memcpy(&g, key, keysz);
83   res = (unsigned int) (g << 8);
84 
85   return res;
86 }
87 
uidcache_create(void)88 static void uidcache_create(void) {
89   if (uid_tab == NULL &&
90       auth_pool != NULL) {
91     int ok = TRUE;
92 
93     uid_tab = pr_table_alloc(auth_pool, 0);
94 
95     if (pr_table_ctl(uid_tab, PR_TABLE_CTL_SET_KEY_CMP,
96         (void *) uid_keycmp_cb) < 0) {
97       pr_trace_msg(trace_channel, 2,
98         "error setting key comparison callback for uidcache: %s",
99         strerror(errno));
100       ok = FALSE;
101     }
102 
103     if (pr_table_ctl(uid_tab, PR_TABLE_CTL_SET_KEY_HASH,
104         (void *) uid_hash_cb) < 0) {
105       pr_trace_msg(trace_channel, 2,
106         "error setting key hash callback for uidcache: %s",
107         strerror(errno));
108       ok = FALSE;
109     }
110 
111     if (!ok) {
112       pr_trace_msg(trace_channel, 2, "%s",
113         "destroying unusable uidcache table");
114       pr_table_free(uid_tab);
115       uid_tab = NULL;
116     }
117   }
118 }
119 
uidcache_add(uid_t uid,const char * name)120 static void uidcache_add(uid_t uid, const char *name) {
121   uidcache_create();
122 
123   if (uid_tab != NULL) {
124     int count;
125 
126     (void) pr_table_rewind(uid_tab);
127     count = pr_table_kexists(uid_tab, (const void *) &uid, sizeof(uid_t));
128     if (count <= 0) {
129       uid_t *cache_uid;
130       size_t namelen;
131 
132       /* Allocate memory for a UID out of the ID cache pool, so that this
133        * UID can be used as a key.
134        */
135       cache_uid = palloc(auth_pool, sizeof(uid_t));
136       *cache_uid = uid;
137 
138       namelen = strlen(name);
139 
140       if (pr_table_kadd(uid_tab, (const void *) cache_uid, sizeof(uid_t),
141           pstrndup(auth_pool, name, namelen), namelen + 1) < 0 &&
142           errno != EEXIST) {
143         pr_trace_msg(trace_channel, 3,
144           "error adding name '%s' for UID %s to the uidcache: %s", name,
145           pr_uid2str(NULL, uid), strerror(errno));
146 
147       } else {
148         pr_trace_msg(trace_channel, 5,
149           "stashed name '%s' for UID %s in the uidcache", name,
150           pr_uid2str(NULL, uid));
151       }
152     }
153   }
154 }
155 
uidcache_get(uid_t uid,char * name,size_t namesz)156 static int uidcache_get(uid_t uid, char *name, size_t namesz) {
157   if (uid_tab != NULL) {
158     const void *v = NULL;
159 
160     v = pr_table_kget(uid_tab, (const void *) &uid, sizeof(uid_t), NULL);
161     if (v != NULL) {
162       memset(name, '\0', namesz);
163       sstrncpy(name, v, namesz);
164 
165       pr_trace_msg(trace_channel, 8,
166         "using name '%s' from uidcache for UID %s", name,
167         pr_uid2str(NULL, uid));
168       return 0;
169     }
170 
171    pr_trace_msg(trace_channel, 9,
172       "no value found in uidcache for UID %s: %s", pr_uid2str(NULL, uid),
173       strerror(errno));
174   }
175 
176   errno = ENOENT;
177   return -1;
178 }
179 
gidcache_create(void)180 static void gidcache_create(void) {
181   if (gid_tab == NULL&&
182       auth_pool != NULL) {
183     int ok = TRUE;
184 
185     gid_tab = pr_table_alloc(auth_pool, 0);
186 
187     if (pr_table_ctl(gid_tab, PR_TABLE_CTL_SET_KEY_CMP,
188         (void *) gid_keycmp_cb) < 0) {
189       pr_trace_msg(trace_channel, 2,
190         "error setting key comparison callback for gidcache: %s",
191         strerror(errno));
192       ok = FALSE;
193     }
194 
195     if (pr_table_ctl(gid_tab, PR_TABLE_CTL_SET_KEY_HASH,
196         (void *) gid_hash_cb) < 0) {
197       pr_trace_msg(trace_channel, 2,
198         "error setting key hash callback for gidcache: %s",
199         strerror(errno));
200       ok = FALSE;
201     }
202 
203     if (!ok) {
204       pr_trace_msg(trace_channel, 2, "%s",
205         "destroying unusable gidcache table");
206       pr_table_free(gid_tab);
207       gid_tab = NULL;
208     }
209   }
210 }
211 
gidcache_add(gid_t gid,const char * name)212 static void gidcache_add(gid_t gid, const char *name) {
213   gidcache_create();
214 
215   if (gid_tab != NULL) {
216     int count;
217 
218     (void) pr_table_rewind(gid_tab);
219     count = pr_table_kexists(gid_tab, (const void *) &gid, sizeof(gid_t));
220     if (count <= 0) {
221       gid_t *cache_gid;
222       size_t namelen;
223 
224       /* Allocate memory for a GID out of the ID cache pool, so that this
225        * GID can be used as a key.
226        */
227       cache_gid = palloc(auth_pool, sizeof(gid_t));
228       *cache_gid = gid;
229 
230       namelen = strlen(name);
231 
232       if (pr_table_kadd(gid_tab, (const void *) cache_gid, sizeof(gid_t),
233           pstrndup(auth_pool, name, namelen), namelen + 1) < 0 &&
234           errno != EEXIST) {
235         pr_trace_msg(trace_channel, 3,
236           "error adding name '%s' for GID %s to the gidcache: %s", name,
237           pr_gid2str(NULL, gid), strerror(errno));
238 
239       } else {
240         pr_trace_msg(trace_channel, 5,
241           "stashed name '%s' for GID %s in the gidcache", name,
242           pr_gid2str(NULL, gid));
243       }
244     }
245   }
246 }
247 
gidcache_get(gid_t gid,char * name,size_t namesz)248 static int gidcache_get(gid_t gid, char *name, size_t namesz) {
249   if (gid_tab != NULL) {
250     const void *v = NULL;
251 
252     v = pr_table_kget(gid_tab, (const void *) &gid, sizeof(gid_t), NULL);
253     if (v != NULL) {
254       memset(name, '\0', namesz);
255       sstrncpy(name, v, namesz);
256 
257       pr_trace_msg(trace_channel, 8,
258         "using name '%s' from gidcache for GID %s", name,
259         pr_gid2str(NULL, gid));
260       return 0;
261     }
262 
263    pr_trace_msg(trace_channel, 9,
264       "no value found in gidcache for GID %s: %s", pr_gid2str(NULL, gid),
265       strerror(errno));
266   }
267 
268   errno = ENOENT;
269   return -1;
270 }
271 
usercache_create(void)272 static void usercache_create(void) {
273   if (user_tab == NULL &&
274       auth_pool != NULL) {
275     user_tab = pr_table_alloc(auth_pool, 0);
276   }
277 }
278 
usercache_add(const char * name,uid_t uid)279 static void usercache_add(const char *name, uid_t uid) {
280   usercache_create();
281 
282   if (user_tab != NULL) {
283     int count;
284 
285     (void) pr_table_rewind(user_tab);
286     count = pr_table_exists(user_tab, name);
287     if (count <= 0) {
288       const char *cache_name;
289       uid_t *cache_key;
290 
291       /* Allocate memory for a key out of the ID cache pool, so that this
292        * name can be used as a key.
293        */
294       cache_name = pstrdup(auth_pool, name);
295       cache_key = palloc(auth_pool, sizeof(uid_t));
296       *cache_key = uid;
297 
298       if (pr_table_add(user_tab, cache_name, cache_key, sizeof(uid_t)) < 0 &&
299           errno != EEXIST) {
300         pr_trace_msg(trace_channel, 3,
301           "error adding UID %s for user '%s' to the usercache: %s",
302           pr_uid2str(NULL, uid), name, strerror(errno));
303 
304       } else {
305         pr_trace_msg(trace_channel, 5,
306           "stashed UID %s for user '%s' in the usercache",
307           pr_uid2str(NULL, uid), name);
308       }
309     }
310   }
311 }
312 
usercache_get(const char * name,uid_t * uid)313 static int usercache_get(const char *name, uid_t *uid) {
314   if (user_tab != NULL) {
315     const void *v = NULL;
316 
317     v = pr_table_get(user_tab, name, NULL);
318     if (v != NULL) {
319       *uid = *((uid_t *) v);
320 
321       pr_trace_msg(trace_channel, 8,
322         "using UID %s for user '%s' from usercache", pr_uid2str(NULL, *uid),
323         name);
324       return 0;
325     }
326 
327    pr_trace_msg(trace_channel, 9,
328       "no value found in usercache for user '%s': %s", name, strerror(errno));
329   }
330 
331   errno = ENOENT;
332   return -1;
333 }
334 
groupcache_create(void)335 static void groupcache_create(void) {
336   if (group_tab == NULL &&
337       auth_pool != NULL) {
338     group_tab = pr_table_alloc(auth_pool, 0);
339   }
340 }
341 
groupcache_add(const char * name,gid_t gid)342 static void groupcache_add(const char *name, gid_t gid) {
343   groupcache_create();
344 
345   if (group_tab != NULL) {
346     int count;
347 
348     (void) pr_table_rewind(group_tab);
349     count = pr_table_exists(group_tab, name);
350     if (count <= 0) {
351       const char *cache_name;
352       gid_t *cache_key;
353 
354       /* Allocate memory for a key out of the ID cache pool, so that this
355        * name can be used as a key.
356        */
357       cache_name = pstrdup(auth_pool, name);
358       cache_key = palloc(auth_pool, sizeof(gid_t));
359       *cache_key = gid;
360 
361       if (pr_table_add(group_tab, cache_name, cache_key, sizeof(gid_t)) < 0 &&
362           errno != EEXIST) {
363         pr_trace_msg(trace_channel, 3,
364           "error adding GID %s for group '%s' to the groupcache: %s",
365           pr_gid2str(NULL, gid), name, strerror(errno));
366 
367       } else {
368         pr_trace_msg(trace_channel, 5,
369           "stashed GID %s for group '%s' in the groupcache",
370           pr_gid2str(NULL, gid), name);
371       }
372     }
373   }
374 }
375 
groupcache_get(const char * name,gid_t * gid)376 static int groupcache_get(const char *name, gid_t *gid) {
377   if (group_tab != NULL) {
378     const void *v = NULL;
379 
380     v = pr_table_get(group_tab, name, NULL);
381     if (v != NULL) {
382       *gid = *((gid_t *) v);
383 
384       pr_trace_msg(trace_channel, 8,
385         "using GID %s for group '%s' from groupcache", pr_gid2str(NULL, *gid),
386         name);
387       return 0;
388     }
389 
390    pr_trace_msg(trace_channel, 9,
391       "no value found in groupcache for group '%s': %s", name, strerror(errno));
392   }
393 
394   errno = ENOENT;
395   return -1;
396 }
397 
398 /* The difference between this function, and pr_cmd_alloc(), is that this
399  * allocates the cmd_rec directly from the given pool, whereas pr_cmd_alloc()
400  * will allocate a subpool from the given pool, and allocate its cmd_rec
401  * from the subpool.  This means that pr_cmd_alloc()'s cmd_rec's can be
402  * subsequently destroyed easily; this function's cmd_rec's will be destroyed
403  * when the given pool is destroyed.
404  */
make_cmd(pool * cp,unsigned int argc,...)405 static cmd_rec *make_cmd(pool *cp, unsigned int argc, ...) {
406   va_list args;
407   cmd_rec *c;
408   pool *sub_pool;
409 
410   c = pcalloc(cp, sizeof(cmd_rec));
411   c->argc = argc;
412   c->stash_index = -1;
413   c->stash_hash = 0;
414 
415   if (argc > 0) {
416     register unsigned int i;
417 
418     c->argv = pcalloc(cp, sizeof(void *) * (argc + 1));
419 
420     va_start(args, argc);
421 
422     for (i = 0; i < argc; i++) {
423       c->argv[i] = (void *) va_arg(args, char *);
424     }
425 
426     va_end(args);
427 
428     c->argv[argc] = NULL;
429   }
430 
431   /* Make sure we provide pool and tmp_pool for the consumers. */
432   sub_pool = make_sub_pool(cp);
433   c->pool = c->tmp_pool = sub_pool;
434 
435   return c;
436 }
437 
dispatch_auth(cmd_rec * cmd,char * match,module ** m)438 static modret_t *dispatch_auth(cmd_rec *cmd, char *match, module **m) {
439   authtable *start_tab = NULL, *iter_tab = NULL;
440   modret_t *mr = NULL;
441 
442   start_tab = pr_stash_get_symbol2(PR_SYM_AUTH, match, NULL,
443     &cmd->stash_index, &cmd->stash_hash);
444   if (start_tab == NULL) {
445     int xerrno = errno;
446 
447     pr_trace_msg(trace_channel, 1, "error finding start symbol for '%s': %s",
448       match, strerror(xerrno));
449     return PR_ERROR_MSG(cmd, NULL, strerror(xerrno));
450   }
451 
452   iter_tab = start_tab;
453 
454   while (iter_tab) {
455     pr_signals_handle();
456 
457     if (m && *m && *m != iter_tab->m) {
458       goto next;
459     }
460 
461     pr_trace_msg(trace_channel, 6,
462       "dispatching auth request \"%s\" to module mod_%s",
463       match, iter_tab->m->name);
464 
465     mr = pr_module_call(iter_tab->m, iter_tab->handler, cmd);
466 
467     /* Return a pointer, if requested, to the module which answered the
468      * auth request.  This is used, for example, by auth_getpwnam() for
469      * associating the answering auth module with the data looked up.
470      */
471 
472     if (iter_tab->auth_flags & PR_AUTH_FL_REQUIRED) {
473       pr_trace_msg(trace_channel, 6,
474         "\"%s\" response from module mod_%s is authoritative", match,
475         iter_tab->m->name);
476 
477       if (m) {
478         *m = iter_tab->m;
479       }
480 
481       break;
482     }
483 
484     if (MODRET_ISHANDLED(mr) ||
485         MODRET_ISERROR(mr)) {
486 
487       if (m) {
488         *m = iter_tab->m;
489       }
490 
491       break;
492     }
493 
494   next:
495     iter_tab = pr_stash_get_symbol2(PR_SYM_AUTH, match, iter_tab,
496       &cmd->stash_index, &cmd->stash_hash);
497 
498     if (iter_tab == start_tab) {
499       /* We have looped back to the start.  Break out now and do not loop
500        * around again (and again, and again...)
501        */
502       pr_trace_msg(trace_channel, 15, "reached end of symbols for '%s'", match);
503       mr = PR_DECLINED(cmd);
504       break;
505     }
506   }
507 
508   return mr;
509 }
510 
pr_auth_setpwent(pool * p)511 void pr_auth_setpwent(pool *p) {
512   cmd_rec *cmd = NULL;
513 
514   cmd = make_cmd(p, 0);
515   (void) dispatch_auth(cmd, "setpwent", NULL);
516 
517   if (cmd->tmp_pool) {
518     destroy_pool(cmd->tmp_pool);
519     cmd->tmp_pool = NULL;
520   }
521 
522   return;
523 }
524 
pr_auth_endpwent(pool * p)525 void pr_auth_endpwent(pool *p) {
526   cmd_rec *cmd = NULL;
527 
528   cmd = make_cmd(p, 0);
529   (void) dispatch_auth(cmd, "endpwent", NULL);
530 
531   if (cmd->tmp_pool) {
532     destroy_pool(cmd->tmp_pool);
533     cmd->tmp_pool = NULL;
534   }
535 
536   if (auth_tab) {
537     int item_count;
538 
539     item_count = pr_table_count(auth_tab);
540     pr_trace_msg(trace_channel, 5, "emptying authcache (%d %s)", item_count,
541       item_count != 1 ? "items" : "item");
542 
543     (void) pr_table_empty(auth_tab);
544     (void) pr_table_free(auth_tab);
545     auth_tab = NULL;
546   }
547 
548   return;
549 }
550 
pr_auth_setgrent(pool * p)551 void pr_auth_setgrent(pool *p) {
552   cmd_rec *cmd = NULL;
553 
554   cmd = make_cmd(p, 0);
555   (void) dispatch_auth(cmd, "setgrent", NULL);
556 
557   if (cmd->tmp_pool) {
558     destroy_pool(cmd->tmp_pool);
559     cmd->tmp_pool = NULL;
560   }
561 
562   return;
563 }
564 
pr_auth_endgrent(pool * p)565 void pr_auth_endgrent(pool *p) {
566   cmd_rec *cmd = NULL;
567 
568   cmd = make_cmd(p, 0);
569   (void) dispatch_auth(cmd, "endgrent", NULL);
570 
571   if (cmd->tmp_pool) {
572     destroy_pool(cmd->tmp_pool);
573     cmd->tmp_pool = NULL;
574   }
575 
576   return;
577 }
578 
pr_auth_getpwent(pool * p)579 struct passwd *pr_auth_getpwent(pool *p) {
580   cmd_rec *cmd = NULL;
581   modret_t *mr = NULL;
582   struct passwd *res = NULL;
583 
584   if (p == NULL) {
585     errno = EINVAL;
586     return NULL;
587   }
588 
589   cmd = make_cmd(p, 0);
590   mr = dispatch_auth(cmd, "getpwent", NULL);
591 
592   if (MODRET_ISHANDLED(mr) &&
593       MODRET_HASDATA(mr)) {
594     res = mr->data;
595   }
596 
597   if (cmd->tmp_pool) {
598     destroy_pool(cmd->tmp_pool);
599     cmd->tmp_pool = NULL;
600   }
601 
602   /* Sanity check */
603   if (res == NULL) {
604     return NULL;
605   }
606 
607   /* Make sure the UID and GID are not -1 */
608   if (res->pw_uid == (uid_t) -1) {
609     pr_log_pri(PR_LOG_WARNING, "error: UID of -1 not allowed");
610     errno = ENOENT;
611     return NULL;
612   }
613 
614   if (res->pw_gid == (gid_t) -1) {
615     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
616     errno = ENOENT;
617     return NULL;
618   }
619 
620   return res;
621 }
622 
pr_auth_getgrent(pool * p)623 struct group *pr_auth_getgrent(pool *p) {
624   cmd_rec *cmd = NULL;
625   modret_t *mr = NULL;
626   struct group *res = NULL;
627 
628   if (p == NULL) {
629     errno = EINVAL;
630     return NULL;
631   }
632 
633   cmd = make_cmd(p, 0);
634   mr = dispatch_auth(cmd, "getgrent", NULL);
635 
636   if (MODRET_ISHANDLED(mr) &&
637       MODRET_HASDATA(mr)) {
638     res = mr->data;
639   }
640 
641   if (cmd->tmp_pool) {
642     destroy_pool(cmd->tmp_pool);
643     cmd->tmp_pool = NULL;
644   }
645 
646   /* Sanity check */
647   if (res == NULL) {
648     return NULL;
649   }
650 
651   /* Make sure the GID is not -1 */
652   if (res->gr_gid == (gid_t) -1) {
653     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
654     errno = ENOENT;
655     return NULL;
656   }
657 
658   return res;
659 }
660 
pr_auth_getpwnam(pool * p,const char * name)661 struct passwd *pr_auth_getpwnam(pool *p, const char *name) {
662   cmd_rec *cmd = NULL;
663   modret_t *mr = NULL;
664   struct passwd *res = NULL;
665   module *m = NULL;
666 
667   if (p == NULL ||
668       name == NULL) {
669     errno = EINVAL;
670     return NULL;
671   }
672 
673   cmd = make_cmd(p, 1, name);
674   mr = dispatch_auth(cmd, "getpwnam", &m);
675 
676   if (MODRET_ISHANDLED(mr) &&
677       MODRET_HASDATA(mr)) {
678     res = mr->data;
679   }
680 
681   if (cmd->tmp_pool) {
682     destroy_pool(cmd->tmp_pool);
683     cmd->tmp_pool = NULL;
684   }
685 
686   /* Sanity check */
687   if (res == NULL) {
688     errno = ENOENT;
689     return NULL;
690   }
691 
692   /* Make sure the UID and GID are not -1 */
693   if (res->pw_uid == (uid_t) -1) {
694     pr_log_pri(PR_LOG_WARNING, "error: UID of -1 not allowed");
695     errno = ENOENT;
696     return NULL;
697   }
698 
699   if (res->pw_gid == (gid_t) -1) {
700     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
701     errno = ENOENT;
702     return NULL;
703   }
704 
705   if ((auth_caching & PR_AUTH_CACHE_FL_AUTH_MODULE) &&
706       !auth_tab &&
707       auth_pool) {
708     auth_tab = pr_table_alloc(auth_pool, 0);
709   }
710 
711   if (m &&
712       auth_tab) {
713     int count = 0;
714     void *value = NULL;
715 
716     value = palloc(auth_pool, sizeof(module *));
717     *((module **) value) = m;
718 
719     count = pr_table_exists(auth_tab, name);
720     if (count <= 0) {
721       if (pr_table_add(auth_tab, pstrdup(auth_pool, name), value,
722           sizeof(module *)) < 0) {
723         pr_trace_msg(trace_channel, 3,
724           "error adding module 'mod_%s.c' for user '%s' to the authcache: %s",
725           m->name, name, strerror(errno));
726 
727       } else {
728         pr_trace_msg(trace_channel, 5,
729           "stashed module 'mod_%s.c' for user '%s' in the authcache",
730           m->name, name);
731       }
732 
733     } else {
734       if (pr_table_set(auth_tab, pstrdup(auth_pool, name), value,
735           sizeof(module *)) < 0) {
736         pr_trace_msg(trace_channel, 3,
737           "error setting module 'mod_%s.c' for user '%s' in the authcache: %s",
738           m->name, name, strerror(errno));
739 
740       } else {
741         pr_trace_msg(trace_channel, 5,
742           "stashed module 'mod_%s.c' for user '%s' in the authcache",
743           m->name, name);
744       }
745     }
746   }
747 
748   if (auth_caching & PR_AUTH_CACHE_FL_UID2NAME) {
749     uidcache_add(res->pw_uid, res->pw_name);
750   }
751 
752   if (auth_caching & PR_AUTH_CACHE_FL_NAME2UID) {
753     usercache_add(res->pw_name, res->pw_uid);
754   }
755 
756   /* Get the (possibly rewritten) home directory. */
757   res->pw_dir = (char *) pr_auth_get_home(p, res->pw_dir);
758 
759   pr_log_debug(DEBUG10, "retrieved UID %s for user '%s'",
760     pr_uid2str(NULL, res->pw_uid), name);
761   return res;
762 }
763 
pr_auth_getpwuid(pool * p,uid_t uid)764 struct passwd *pr_auth_getpwuid(pool *p, uid_t uid) {
765   cmd_rec *cmd = NULL;
766   modret_t *mr = NULL;
767   struct passwd *res = NULL;
768 
769   if (p == NULL) {
770     errno = EINVAL;
771     return NULL;
772   }
773 
774   cmd = make_cmd(p, 1, (void *) &uid);
775   mr = dispatch_auth(cmd, "getpwuid", NULL);
776 
777   if (MODRET_ISHANDLED(mr) &&
778       MODRET_HASDATA(mr)) {
779     res = mr->data;
780   }
781 
782   if (cmd->tmp_pool) {
783     destroy_pool(cmd->tmp_pool);
784     cmd->tmp_pool = NULL;
785   }
786 
787   /* Sanity check */
788   if (res == NULL) {
789     errno = ENOENT;
790     return NULL;
791   }
792 
793   /* Make sure the UID and GID are not -1 */
794   if (res->pw_uid == (uid_t) -1) {
795     pr_log_pri(PR_LOG_WARNING, "error: UID of -1 not allowed");
796     errno = ENOENT;
797     return NULL;
798   }
799 
800   if (res->pw_gid == (gid_t) -1) {
801     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
802     errno = ENOENT;
803     return NULL;
804   }
805 
806   pr_log_debug(DEBUG10, "retrieved user '%s' for UID %s",
807     res->pw_name, pr_uid2str(NULL, uid));
808   return res;
809 }
810 
pr_auth_getgrnam(pool * p,const char * name)811 struct group *pr_auth_getgrnam(pool *p, const char *name) {
812   cmd_rec *cmd = NULL;
813   modret_t *mr = NULL;
814   struct group *res = NULL;
815 
816   if (p == NULL ||
817       name == NULL) {
818     errno = EINVAL;
819     return NULL;
820   }
821 
822   cmd = make_cmd(p, 1, name);
823   mr = dispatch_auth(cmd, "getgrnam", NULL);
824 
825   if (MODRET_ISHANDLED(mr) &&
826       MODRET_HASDATA(mr)) {
827     res = mr->data;
828   }
829 
830   if (cmd->tmp_pool) {
831     destroy_pool(cmd->tmp_pool);
832     cmd->tmp_pool = NULL;
833   }
834 
835   /* Sanity check */
836   if (res == NULL) {
837     errno = ENOENT;
838     return NULL;
839   }
840 
841   /* Make sure the GID is not -1 */
842   if (res->gr_gid == (gid_t) -1) {
843     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
844     errno = ENOENT;
845     return NULL;
846   }
847 
848   if (auth_caching & PR_AUTH_CACHE_FL_GID2NAME) {
849     gidcache_add(res->gr_gid, name);
850   }
851 
852   if (auth_caching & PR_AUTH_CACHE_FL_NAME2GID) {
853     groupcache_add(name, res->gr_gid);
854   }
855 
856   pr_log_debug(DEBUG10, "retrieved GID %s for group '%s'",
857     pr_gid2str(NULL, res->gr_gid), name);
858   return res;
859 }
860 
pr_auth_getgrgid(pool * p,gid_t gid)861 struct group *pr_auth_getgrgid(pool *p, gid_t gid) {
862   cmd_rec *cmd = NULL;
863   modret_t *mr = NULL;
864   struct group *res = NULL;
865 
866   if (p == NULL) {
867     errno = EINVAL;
868     return NULL;
869   }
870 
871   cmd = make_cmd(p, 1, (void *) &gid);
872   mr = dispatch_auth(cmd, "getgrgid", NULL);
873 
874   if (MODRET_ISHANDLED(mr) &&
875       MODRET_HASDATA(mr)) {
876     res = mr->data;
877   }
878 
879   if (cmd->tmp_pool) {
880     destroy_pool(cmd->tmp_pool);
881     cmd->tmp_pool = NULL;
882   }
883 
884   /* Sanity check */
885   if (res == NULL) {
886     errno = ENOENT;
887     return NULL;
888   }
889 
890   /* Make sure the GID is not -1 */
891   if (res->gr_gid == (gid_t) -1) {
892     pr_log_pri(PR_LOG_WARNING, "error: GID of -1 not allowed");
893     errno = ENOENT;
894     return NULL;
895   }
896 
897   pr_log_debug(DEBUG10, "retrieved group '%s' for GID %lu",
898     res->gr_name, (unsigned long) gid);
899   return res;
900 }
901 
get_authcode_str(int auth_code)902 static const char *get_authcode_str(int auth_code) {
903   const char *name = "(unknown)";
904 
905   switch (auth_code) {
906     case PR_AUTH_OK_NO_PASS:
907       name = "OK_NO_PASS";
908       break;
909 
910     case PR_AUTH_RFC2228_OK:
911       name = "RFC2228_OK";
912       break;
913 
914     case PR_AUTH_OK:
915       name = "OK";
916       break;
917 
918     case PR_AUTH_ERROR:
919       name = "ERROR";
920       break;
921 
922     case PR_AUTH_NOPWD:
923       name = "NOPWD";
924       break;
925 
926     case PR_AUTH_BADPWD:
927       name = "BADPWD";
928       break;
929 
930     case PR_AUTH_AGEPWD:
931       name = "AGEPWD";
932       break;
933 
934     case PR_AUTH_DISABLEDPWD:
935       name = "DISABLEDPWD";
936       break;
937 
938     case PR_AUTH_CRED_INSUFFICIENT:
939       name = "CRED_INSUFFICIENT";
940       break;
941 
942     case PR_AUTH_CRED_UNAVAIL:
943       name = "CRED_UNAVAIL";
944       break;
945 
946     case PR_AUTH_CRED_ERROR:
947       name = "CRED_ERROR";
948       break;
949 
950     case PR_AUTH_INFO_UNAVAIL:
951       name = "INFO_UNAVAIL";
952       break;
953 
954     case PR_AUTH_MAX_ATTEMPTS_EXCEEDED:
955       name = "MAX_ATTEMPTS_EXCEEDED";
956       break;
957 
958     case PR_AUTH_INIT_ERROR:
959       name = "INIT_ERROR";
960       break;
961 
962     case PR_AUTH_NEW_TOKEN_REQUIRED:
963       name = "NEW_TOKEN_REQUIRED";
964       break;
965 
966     default:
967       break;
968   }
969 
970   return name;
971 }
972 
pr_auth_authenticate(pool * p,const char * name,const char * pw)973 int pr_auth_authenticate(pool *p, const char *name, const char *pw) {
974   cmd_rec *cmd = NULL;
975   modret_t *mr = NULL;
976   module *m = NULL;
977   int res = PR_AUTH_NOPWD;
978 
979   if (p == NULL ||
980       name == NULL ||
981       pw == NULL) {
982     errno = EINVAL;
983     return -1;
984   }
985 
986   cmd = make_cmd(p, 2, name, pw);
987 
988   /* First, check for any of the modules in the "authenticating only" list
989    * of modules.  This is usually only mod_auth_pam, but other modules
990    * might also add themselves (e.g. mod_radius under certain conditions).
991    */
992   if (auth_module_list) {
993     struct auth_module_elt *elt;
994 
995     for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt;
996         elt = elt->next) {
997       pr_signals_handle();
998 
999       pr_trace_msg(trace_channel, 7, "checking with auth-only module '%s'",
1000         elt->name);
1001 
1002       m = pr_module_get(elt->name);
1003       if (m) {
1004         mr = dispatch_auth(cmd, "auth", &m);
1005 
1006         if (MODRET_ISHANDLED(mr)) {
1007           pr_trace_msg(trace_channel, 4,
1008             "module '%s' used for authenticating user '%s'", elt->name, name);
1009 
1010           res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK;
1011 
1012           if (cmd->tmp_pool) {
1013             destroy_pool(cmd->tmp_pool);
1014             cmd->tmp_pool = NULL;
1015           }
1016 
1017           pr_trace_msg(trace_channel, 9,
1018             "module '%s' returned HANDLED (%s) for authenticating user '%s'",
1019             elt->name, get_authcode_str(res), name);
1020           return res;
1021         }
1022 
1023         if (MODRET_ISERROR(mr)) {
1024           res = MODRET_ERROR(mr);
1025 
1026           if (cmd->tmp_pool) {
1027             destroy_pool(cmd->tmp_pool);
1028             cmd->tmp_pool = NULL;
1029           }
1030 
1031           pr_trace_msg(trace_channel, 9,
1032             "module '%s' returned ERROR (%s) for authenticating user '%s'",
1033             elt->name, get_authcode_str(res), name);
1034           return res;
1035         }
1036 
1037         m = NULL;
1038       }
1039     }
1040   }
1041 
1042   if (auth_tab != NULL) {
1043     const void *v;
1044 
1045     /* Fetch the specific module to be used for authenticating this user. */
1046     v = pr_table_get(auth_tab, name, NULL);
1047     if (v != NULL) {
1048       m = *((module **) v);
1049 
1050       pr_trace_msg(trace_channel, 4,
1051         "using module 'mod_%s.c' from authcache to authenticate user '%s'",
1052         m->name, name);
1053     }
1054   }
1055 
1056   mr = dispatch_auth(cmd, "auth", m ? &m : NULL);
1057 
1058   if (MODRET_ISHANDLED(mr)) {
1059     res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK;
1060     pr_trace_msg(trace_channel, 9,
1061       "obtained HANDLED (%s) for authenticating user '%s'",
1062       get_authcode_str(res), name);
1063 
1064   } else if (MODRET_ISERROR(mr)) {
1065     res = MODRET_ERROR(mr);
1066     pr_trace_msg(trace_channel, 9,
1067       "obtained ERROR (%s) for authenticating user '%s'", get_authcode_str(res),
1068       name);
1069   }
1070 
1071   if (cmd->tmp_pool) {
1072     destroy_pool(cmd->tmp_pool);
1073     cmd->tmp_pool = NULL;
1074   }
1075 
1076   return res;
1077 }
1078 
pr_auth_authorize(pool * p,const char * name)1079 int pr_auth_authorize(pool *p, const char *name) {
1080   cmd_rec *cmd = NULL;
1081   modret_t *mr = NULL;
1082   module *m = NULL;
1083   int res = PR_AUTH_OK;
1084 
1085   if (p == NULL ||
1086       name == NULL) {
1087     errno = EINVAL;
1088     return -1;
1089   }
1090 
1091   cmd = make_cmd(p, 1, name);
1092 
1093   if (auth_tab != NULL) {
1094     const void *v;
1095 
1096     /* Fetch the specific module to be used for authenticating this user. */
1097     v = pr_table_get(auth_tab, name, NULL);
1098     if (v != NULL) {
1099       m = *((module **) v);
1100 
1101       pr_trace_msg(trace_channel, 4,
1102         "using module 'mod_%s.c' from authcache to authorize user '%s'",
1103         m->name, name);
1104     }
1105   }
1106 
1107   mr = dispatch_auth(cmd, "authorize", m ? &m : NULL);
1108 
1109   /* Unlike the other auth calls, we assume here that unless the handlers
1110    * explicitly return ERROR, the user is authorized.  Thus HANDLED and
1111    * DECLINED are both treated as "yes, this user is authorized".  This
1112    * handles the case where the authenticating module (e.g. mod_sql)
1113    * does NOT provide an 'authorize' handler.
1114    */
1115 
1116   if (MODRET_ISERROR(mr)) {
1117     res = MODRET_ERROR(mr);
1118     pr_trace_msg(trace_channel, 9,
1119       "obtained ERROR (%s) for authorizing user '%s'", get_authcode_str(res),
1120       name);
1121   }
1122 
1123   if (cmd->tmp_pool) {
1124     destroy_pool(cmd->tmp_pool);
1125     cmd->tmp_pool = NULL;
1126   }
1127 
1128   return res;
1129 }
1130 
pr_auth_check(pool * p,const char * ciphertext_passwd,const char * name,const char * cleartext_passwd)1131 int pr_auth_check(pool *p, const char *ciphertext_passwd, const char *name,
1132     const char *cleartext_passwd) {
1133   cmd_rec *cmd = NULL;
1134   modret_t *mr = NULL;
1135   module *m = NULL;
1136   int res = PR_AUTH_BADPWD;
1137   size_t cleartext_passwd_len = 0;
1138 
1139   /* Note: it's possible for ciphertext_passwd to be NULL (mod_ldap might do
1140    * this, for example), so we cannot enforce that it be non-NULL.
1141    */
1142 
1143   if (p == NULL ||
1144       name == NULL ||
1145       cleartext_passwd == NULL) {
1146     errno = EINVAL;
1147     return -1;
1148   }
1149 
1150   cleartext_passwd_len = strlen(cleartext_passwd);
1151   if (cleartext_passwd_len > auth_max_passwd_len) {
1152     pr_log_auth(PR_LOG_INFO,
1153       "client-provided password size exceeds MaxPasswordSize (%lu), "
1154       "rejecting", (unsigned long) auth_max_passwd_len);
1155     errno = EPERM;
1156     return -1;
1157   }
1158 
1159   cmd = make_cmd(p, 3, ciphertext_passwd, name, cleartext_passwd);
1160 
1161   /* First, check for any of the modules in the "authenticating only" list
1162    * of modules.  This is usually only mod_auth_pam, but other modules
1163    * might also add themselves (e.g. mod_radius under certain conditions).
1164    */
1165   if (auth_module_list) {
1166     struct auth_module_elt *elt;
1167 
1168     for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt;
1169         elt = elt->next) {
1170       pr_signals_handle();
1171 
1172       m = pr_module_get(elt->name);
1173       if (m) {
1174         mr = dispatch_auth(cmd, "check", &m);
1175 
1176         if (MODRET_ISHANDLED(mr)) {
1177           pr_trace_msg(trace_channel, 4,
1178             "module '%s' used for authenticating user '%s'", elt->name, name);
1179 
1180           res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK;
1181 
1182           if (cmd->tmp_pool) {
1183             destroy_pool(cmd->tmp_pool);
1184             cmd->tmp_pool = NULL;
1185           }
1186 
1187           pr_trace_msg(trace_channel, 9,
1188             "module '%s' returned HANDLED (%s) for checking user '%s'",
1189             elt->name, get_authcode_str(res), name);
1190           return res;
1191         }
1192 
1193         if (MODRET_ISERROR(mr)) {
1194           res = MODRET_ERROR(mr);
1195 
1196           if (cmd->tmp_pool) {
1197             destroy_pool(cmd->tmp_pool);
1198             cmd->tmp_pool = NULL;
1199           }
1200 
1201           pr_trace_msg(trace_channel, 9,
1202             "module '%s' returned ERROR (%s) for checking user '%s'",
1203             elt->name, get_authcode_str(res), name);
1204           return res;
1205         }
1206 
1207         m = NULL;
1208       }
1209     }
1210   }
1211 
1212   if (auth_tab != NULL) {
1213     const void *v;
1214 
1215     /* Fetch the specific module to be used for authenticating this user. */
1216     v = pr_table_get(auth_tab, name, NULL);
1217     if (v != NULL) {
1218       m = *((module **) v);
1219 
1220       pr_trace_msg(trace_channel, 4,
1221         "using module 'mod_%s.c' from authcache to authenticate user '%s'",
1222         m->name, name);
1223     }
1224   }
1225 
1226   mr = dispatch_auth(cmd, "check", m ? &m : NULL);
1227 
1228   if (MODRET_ISHANDLED(mr)) {
1229     res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK;
1230     pr_trace_msg(trace_channel, 9,
1231       "obtained HANDLED (%s) for checking user '%s'", get_authcode_str(res),
1232       name);
1233   }
1234 
1235   if (cmd->tmp_pool) {
1236     destroy_pool(cmd->tmp_pool);
1237     cmd->tmp_pool = NULL;
1238   }
1239 
1240   return res;
1241 }
1242 
pr_auth_requires_pass(pool * p,const char * name)1243 int pr_auth_requires_pass(pool *p, const char *name) {
1244   cmd_rec *cmd;
1245   modret_t *mr;
1246   int res = TRUE;
1247 
1248   if (p == NULL ||
1249       name == NULL) {
1250     errno = EINVAL;
1251     return -1;
1252   }
1253 
1254   cmd = make_cmd(p, 1, name);
1255   mr = dispatch_auth(cmd, "requires_pass", NULL);
1256 
1257   if (MODRET_ISHANDLED(mr)) {
1258     res = FALSE;
1259 
1260   } else if (MODRET_ISERROR(mr)) {
1261     res = MODRET_ERROR(mr);
1262   }
1263 
1264   if (cmd->tmp_pool) {
1265     destroy_pool(cmd->tmp_pool);
1266     cmd->tmp_pool = NULL;
1267   }
1268 
1269   return res;
1270 }
1271 
pr_auth_uid2name(pool * p,uid_t uid)1272 const char *pr_auth_uid2name(pool *p, uid_t uid) {
1273   static char namebuf[PR_TUNABLE_LOGIN_MAX+1];
1274   cmd_rec *cmd = NULL;
1275   modret_t *mr = NULL;
1276   char *res = NULL;
1277   unsigned int cache_lookup_flags = (PR_AUTH_CACHE_FL_UID2NAME|PR_AUTH_CACHE_FL_BAD_UID2NAME);
1278   int have_name = FALSE;
1279 
1280   if (p == NULL) {
1281     errno = EINVAL;
1282     return NULL;
1283   }
1284 
1285   uidcache_create();
1286 
1287   if (auth_caching & cache_lookup_flags) {
1288     if (uidcache_get(uid, namebuf, sizeof(namebuf)) == 0) {
1289       res = namebuf;
1290       return res;
1291     }
1292   }
1293 
1294   cmd = make_cmd(p, 1, (void *) &uid);
1295   mr = dispatch_auth(cmd, "uid2name", NULL);
1296 
1297   if (MODRET_ISHANDLED(mr) &&
1298       MODRET_HASDATA(mr)) {
1299     res = mr->data;
1300     sstrncpy(namebuf, res, sizeof(namebuf));
1301     res = namebuf;
1302 
1303     if (auth_caching & PR_AUTH_CACHE_FL_UID2NAME) {
1304       uidcache_add(uid, res);
1305     }
1306 
1307     have_name = TRUE;
1308   }
1309 
1310   if (cmd->tmp_pool) {
1311     destroy_pool(cmd->tmp_pool);
1312     cmd->tmp_pool = NULL;
1313   }
1314 
1315   if (!have_name) {
1316     /* TODO: This conversion is data type sensitive, per Bug#4164. */
1317     pr_snprintf(namebuf, sizeof(namebuf)-1, "%lu", (unsigned long) uid);
1318     res = namebuf;
1319 
1320     if (auth_caching & PR_AUTH_CACHE_FL_BAD_UID2NAME) {
1321       uidcache_add(uid, res);
1322     }
1323   }
1324 
1325   return res;
1326 }
1327 
pr_auth_gid2name(pool * p,gid_t gid)1328 const char *pr_auth_gid2name(pool *p, gid_t gid) {
1329   static char namebuf[PR_TUNABLE_LOGIN_MAX+1];
1330   cmd_rec *cmd = NULL;
1331   modret_t *mr = NULL;
1332   char *res = NULL;
1333   unsigned int cache_lookup_flags = (PR_AUTH_CACHE_FL_GID2NAME|PR_AUTH_CACHE_FL_BAD_GID2NAME);
1334   int have_name = FALSE;
1335 
1336   if (p == NULL) {
1337     errno = EINVAL;
1338     return NULL;
1339   }
1340 
1341   gidcache_create();
1342 
1343   if (auth_caching & cache_lookup_flags) {
1344     if (gidcache_get(gid, namebuf, sizeof(namebuf)) == 0) {
1345       res = namebuf;
1346       return res;
1347     }
1348   }
1349 
1350   cmd = make_cmd(p, 1, (void *) &gid);
1351   mr = dispatch_auth(cmd, "gid2name", NULL);
1352 
1353   if (MODRET_ISHANDLED(mr) &&
1354       MODRET_HASDATA(mr)) {
1355     res = mr->data;
1356     sstrncpy(namebuf, res, sizeof(namebuf));
1357     res = namebuf;
1358 
1359     if (auth_caching & PR_AUTH_CACHE_FL_GID2NAME) {
1360       gidcache_add(gid, res);
1361     }
1362 
1363     have_name = TRUE;
1364   }
1365 
1366   if (cmd->tmp_pool) {
1367     destroy_pool(cmd->tmp_pool);
1368     cmd->tmp_pool = NULL;
1369   }
1370 
1371   if (!have_name) {
1372     /* TODO: This conversion is data type sensitive, per Bug#4164. */
1373     pr_snprintf(namebuf, sizeof(namebuf)-1, "%lu", (unsigned long) gid);
1374     res = namebuf;
1375 
1376     if (auth_caching & PR_AUTH_CACHE_FL_BAD_GID2NAME) {
1377       gidcache_add(gid, res);
1378     }
1379   }
1380 
1381   return res;
1382 }
1383 
pr_auth_name2uid(pool * p,const char * name)1384 uid_t pr_auth_name2uid(pool *p, const char *name) {
1385   cmd_rec *cmd = NULL;
1386   modret_t *mr = NULL;
1387   uid_t res = (uid_t) -1;
1388   unsigned int cache_lookup_flags = (PR_AUTH_CACHE_FL_NAME2UID|PR_AUTH_CACHE_FL_BAD_NAME2UID);
1389   int have_id = FALSE;
1390 
1391   if (p == NULL ||
1392       name == NULL) {
1393     errno = EINVAL;
1394     return (uid_t) -1;
1395   }
1396 
1397   usercache_create();
1398 
1399   if (auth_caching & cache_lookup_flags) {
1400     uid_t cache_uid;
1401 
1402     if (usercache_get(name, &cache_uid) == 0) {
1403       res = cache_uid;
1404 
1405       if (res == (uid_t) -1) {
1406         errno = ENOENT;
1407       }
1408 
1409       return res;
1410     }
1411   }
1412 
1413   cmd = make_cmd(p, 1, name);
1414   mr = dispatch_auth(cmd, "name2uid", NULL);
1415 
1416   if (MODRET_ISHANDLED(mr) &&
1417       MODRET_HASDATA(mr)) {
1418     res = *((uid_t *) mr->data);
1419 
1420     if (auth_caching & PR_AUTH_CACHE_FL_NAME2UID) {
1421       usercache_add(name, res);
1422     }
1423 
1424     have_id = TRUE;
1425 
1426   } else {
1427     errno = ENOENT;
1428   }
1429 
1430   if (cmd->tmp_pool) {
1431     destroy_pool(cmd->tmp_pool);
1432     cmd->tmp_pool = NULL;
1433   }
1434 
1435   if (!have_id &&
1436       (auth_caching & PR_AUTH_CACHE_FL_BAD_NAME2UID)) {
1437     usercache_add(name, res);
1438   }
1439 
1440   return res;
1441 }
1442 
pr_auth_name2gid(pool * p,const char * name)1443 gid_t pr_auth_name2gid(pool *p, const char *name) {
1444   cmd_rec *cmd = NULL;
1445   modret_t *mr = NULL;
1446   gid_t res = (gid_t) -1;
1447   unsigned int cache_lookup_flags = (PR_AUTH_CACHE_FL_NAME2GID|PR_AUTH_CACHE_FL_BAD_NAME2GID);
1448   int have_id = FALSE;
1449 
1450   if (p == NULL ||
1451       name == NULL) {
1452     errno = EINVAL;
1453     return (gid_t) -1;
1454   }
1455 
1456   groupcache_create();
1457 
1458   if (auth_caching & cache_lookup_flags) {
1459     gid_t cache_gid;
1460 
1461     if (groupcache_get(name, &cache_gid) == 0) {
1462       res = cache_gid;
1463 
1464       if (res == (gid_t) -1) {
1465         errno = ENOENT;
1466       }
1467 
1468       return res;
1469     }
1470   }
1471 
1472   cmd = make_cmd(p, 1, name);
1473   mr = dispatch_auth(cmd, "name2gid", NULL);
1474 
1475   if (MODRET_ISHANDLED(mr) &&
1476       MODRET_HASDATA(mr)) {
1477     res = *((gid_t *) mr->data);
1478 
1479     if (auth_caching & PR_AUTH_CACHE_FL_NAME2GID) {
1480       groupcache_add(name, res);
1481     }
1482 
1483     have_id = TRUE;
1484 
1485   } else {
1486     errno = ENOENT;
1487   }
1488 
1489   if (cmd->tmp_pool) {
1490     destroy_pool(cmd->tmp_pool);
1491     cmd->tmp_pool = NULL;
1492   }
1493 
1494   if (!have_id &&
1495       (auth_caching & PR_AUTH_CACHE_FL_BAD_NAME2GID)) {
1496     groupcache_add(name, res);
1497   }
1498 
1499   return res;
1500 }
1501 
pr_auth_getgroups(pool * p,const char * name,array_header ** group_ids,array_header ** group_names)1502 int pr_auth_getgroups(pool *p, const char *name, array_header **group_ids,
1503     array_header **group_names) {
1504   cmd_rec *cmd = NULL;
1505   modret_t *mr = NULL;
1506   int res = -1;
1507 
1508   if (p == NULL ||
1509       name == NULL) {
1510     errno = EINVAL;
1511     return -1;
1512   }
1513 
1514   /* Allocate memory for the array_headers of GIDs and group names. */
1515   if (group_ids) {
1516     *group_ids = make_array(permanent_pool, 2, sizeof(gid_t));
1517   }
1518 
1519   if (group_names) {
1520     *group_names = make_array(permanent_pool, 2, sizeof(char *));
1521   }
1522 
1523   cmd = make_cmd(p, 3, name, group_ids ? *group_ids : NULL,
1524     group_names ? *group_names : NULL);
1525 
1526   mr = dispatch_auth(cmd, "getgroups", NULL);
1527 
1528   if (MODRET_ISHANDLED(mr) &&
1529       MODRET_HASDATA(mr)) {
1530     res = *((int *) mr->data);
1531 
1532     /* Note: the number of groups returned should, barring error,
1533      * always be at least 1, as per getgroups(2) behavior.  This one
1534      * ID is present because it is the primary group membership set in
1535      * struct passwd, from /etc/passwd.  This will need to be documented
1536      * for the benefit of auth_getgroup() implementors.
1537      */
1538 
1539     if (group_ids) {
1540       register unsigned int i;
1541       char *strgids = "";
1542       gid_t *gids = (*group_ids)->elts;
1543 
1544       for (i = 0; i < (*group_ids)->nelts; i++) {
1545         pr_signals_handle();
1546         strgids = pstrcat(p, strgids, i != 0 ? ", " : "",
1547           pr_gid2str(NULL, gids[i]), NULL);
1548       }
1549 
1550       pr_log_debug(DEBUG10, "retrieved group %s: %s",
1551         (*group_ids)->nelts == 1 ? "ID" : "IDs",
1552         *strgids ? strgids : "(None; corrupted group file?)");
1553     }
1554 
1555     if (group_names) {
1556       register unsigned int i;
1557       char *strgroups = "";
1558       char **groups = (*group_names)->elts;
1559 
1560       for (i = 0; i < (*group_names)->nelts; i++) {
1561         pr_signals_handle();
1562         strgroups = pstrcat(p, strgroups, i != 0 ? ", " : "", groups[i], NULL);
1563       }
1564 
1565       pr_log_debug(DEBUG10, "retrieved group %s: %s",
1566         (*group_names)->nelts == 1 ? "name" : "names",
1567         *strgroups ? strgroups : "(None; corrupted group file?)");
1568     }
1569   }
1570 
1571   if (cmd->tmp_pool) {
1572     destroy_pool(cmd->tmp_pool);
1573     cmd->tmp_pool = NULL;
1574   }
1575 
1576   return res;
1577 }
1578 
1579 /* This is one messy function.  Yuck.  Yay legacy code. */
pr_auth_get_anon_config(pool * p,const char ** login_user,char ** real_user,char ** anon_name)1580 config_rec *pr_auth_get_anon_config(pool *p, const char **login_user,
1581     char **real_user, char **anon_name) {
1582   config_rec *c = NULL, *alias_config = NULL, *anon_config = NULL;
1583   char *config_user_name = NULL, *config_anon_name = NULL;
1584   unsigned char is_alias = FALSE, *auth_alias_only = NULL;
1585   unsigned long config_flags = (PR_CONFIG_FIND_FL_SKIP_DIR|PR_CONFIG_FIND_FL_SKIP_LIMIT|PR_CONFIG_FIND_FL_SKIP_DYNDIR);
1586 
1587   /* Precedence rules:
1588    *   1. Search for UserAlias directive.
1589    *   2. Search for Anonymous directive.
1590    *   3. Normal user login
1591    */
1592 
1593   config_user_name = get_param_ptr(main_server->conf, "UserName", FALSE);
1594   if (config_user_name != NULL &&
1595       real_user != NULL) {
1596     *real_user = config_user_name;
1597   }
1598 
1599   /* If the main_server->conf->set list is large (e.g. there are many
1600    * config_recs in the list, as can happen if MANY <Directory> sections are
1601    * configured), the login can timeout because this find_config() call takes
1602    * a long time.  The reason this issue strikes HERE first in the login
1603    * process is that this appears to the first find_config() call which has
1604    * a TRUE recurse flag.
1605    *
1606    * The find_config() call below is looking for a UserAlias directive
1607    * anywhere in the configuration, no matter how deeply buried in nested
1608    * config contexts it might be.
1609    */
1610 
1611   c = find_config2(main_server->conf, CONF_PARAM, "UserAlias", TRUE,
1612     config_flags);
1613   if (c != NULL) {
1614     do {
1615       const char *alias;
1616 
1617       pr_signals_handle();
1618 
1619       alias = c->argv[0];
1620       if (strncmp(alias, "*", 2) == 0 ||
1621           strcmp(alias, *login_user) == 0) {
1622         is_alias = TRUE;
1623         alias_config = c;
1624         break;
1625       }
1626 
1627     } while ((c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias",
1628       TRUE, config_flags)) != NULL);
1629   }
1630 
1631   /* This is where things get messy, rapidly. */
1632   if (is_alias == TRUE) {
1633     c = alias_config;
1634   }
1635 
1636   while (c != NULL &&
1637          c->parent != NULL &&
1638          (auth_alias_only = get_param_ptr(c->parent->subset, "AuthAliasOnly", FALSE))) {
1639 
1640     pr_signals_handle();
1641 
1642     /* If AuthAliasOnly is on, ignore this one and continue. */
1643     if (auth_alias_only != NULL &&
1644         *auth_alias_only == TRUE) {
1645       c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias", TRUE,
1646         config_flags);
1647       continue;
1648     }
1649 
1650     /* At this point, we have found an "AuthAliasOnly off" config in
1651      * c->parent->set (which means that we cannot use the UserAlias, and thus
1652      * is_alias is set to false).  See if there's a UserAlias in the same
1653      * config set.
1654      */
1655 
1656     is_alias = FALSE;
1657 
1658     find_config_set_top(alias_config);
1659     c = find_config_next2(c, c->next, CONF_PARAM, "UserAlias", TRUE,
1660       config_flags);
1661 
1662     if (c != NULL &&
1663         (strncmp(c->argv[0], "*", 2) == 0 ||
1664          strcmp(c->argv[0], *login_user) == 0)) {
1665       is_alias = TRUE;
1666       alias_config = c;
1667     }
1668   }
1669 
1670   /* At this point in time, c is guaranteed (if not null) to be pointing at
1671    * a UserAlias config, either the original OR one found in the AuthAliasOnly
1672    * config set.
1673    */
1674   if (c != NULL) {
1675     *login_user = c->argv[1];
1676 
1677     /* If the alias is applied inside an <Anonymous> context, we have found
1678      * our <Anonymous> section.
1679      */
1680     if (c->parent &&
1681         c->parent->config_type == CONF_ANON) {
1682       anon_config = c->parent;
1683 
1684     } else {
1685       c = NULL;
1686     }
1687   }
1688 
1689   /* Next, search for an anonymous entry. */
1690   if (anon_config == NULL) {
1691     c = find_config(main_server->conf, CONF_ANON, NULL, FALSE);
1692 
1693   } else {
1694     find_config_set_top(anon_config);
1695     c = anon_config;
1696   }
1697 
1698   /* If anon_config is null here but c is not null, then we may have found
1699    * a candidate <Anonymous> section.  Let's examine it more closely.
1700    */
1701   if (c != NULL) {
1702     config_rec *starting_c;
1703 
1704     starting_c = c;
1705     do {
1706       pr_signals_handle();
1707 
1708       config_anon_name = get_param_ptr(c->subset, "UserName", FALSE);
1709       if (config_anon_name == NULL) {
1710         config_anon_name = config_user_name;
1711       }
1712 
1713       if (config_anon_name != NULL &&
1714           strcmp(config_anon_name, *login_user) == 0) {
1715 
1716         /* We found our <Anonymous> section. */
1717         anon_config = c;
1718 
1719         if (anon_name != NULL) {
1720           *anon_name = config_anon_name;
1721         }
1722         break;
1723       }
1724 
1725     } while ((c = find_config_next(c, c->next, CONF_ANON, NULL,
1726       FALSE)) != NULL);
1727 
1728     c = starting_c;
1729   }
1730 
1731   if (is_alias == FALSE) {
1732     auth_alias_only = get_param_ptr(c ? c->subset : main_server->conf,
1733       "AuthAliasOnly", FALSE);
1734 
1735     if (auth_alias_only != NULL &&
1736         *auth_alias_only == TRUE) {
1737       if (c != NULL &&
1738           c->config_type == CONF_ANON) {
1739         c = NULL;
1740 
1741       } else {
1742         *login_user = NULL;
1743       }
1744 
1745       /* Note: We only need to look for AuthAliasOnly in main_server IFF
1746        * c is NOT null.  If c IS null, then we will already have looked up
1747        * AuthAliasOnly in main_server above.
1748        */
1749       if (c != NULL) {
1750         auth_alias_only = get_param_ptr(main_server->conf, "AuthAliasOnly",
1751           FALSE);
1752       }
1753 
1754       if (login_user != NULL &&
1755           auth_alias_only != NULL &&
1756           *auth_alias_only == TRUE) {
1757         *login_user = NULL;
1758       }
1759 
1760       if ((login_user == NULL || anon_config == NULL) &&
1761           anon_name != NULL) {
1762         *anon_name = NULL;
1763       }
1764     }
1765 
1766   } else {
1767     config_rec *alias_parent_config = NULL;
1768 
1769     /* We have found a matching UserAlias for the USER name sent by the client.
1770      * But we need to properly handle any AuthAliasOnly directives in that
1771      * config as well (Bug#2070).
1772      */
1773     if (alias_config != NULL) {
1774       alias_parent_config = alias_config->parent;
1775     }
1776 
1777     auth_alias_only = get_param_ptr(alias_parent_config ?
1778       alias_parent_config->subset : main_server->conf, "AuthAliasOnly", FALSE);
1779 
1780     if (auth_alias_only != NULL &&
1781         *auth_alias_only == TRUE) {
1782       if (alias_parent_config != NULL &&
1783           alias_parent_config->config_type == CONF_ANON) {
1784         anon_config = alias_parent_config;
1785       }
1786     }
1787   }
1788 
1789   if (anon_config != NULL) {
1790     config_user_name = get_param_ptr(anon_config->subset, "UserName", FALSE);
1791     if (config_user_name != NULL &&
1792         real_user != NULL) {
1793       *real_user = config_user_name;
1794     }
1795   }
1796 
1797   return anon_config;
1798 }
1799 
pr_auth_banned_by_ftpusers(xaset_t * ctx,const char * user)1800 int pr_auth_banned_by_ftpusers(xaset_t *ctx, const char *user) {
1801   int res = FALSE;
1802   unsigned char *use_ftp_users;
1803 
1804   if (user == NULL) {
1805     return res;
1806   }
1807 
1808   use_ftp_users = get_param_ptr(ctx, "UseFtpUsers", FALSE);
1809   if (use_ftp_users == NULL ||
1810       *use_ftp_users == TRUE) {
1811     FILE *fh = NULL;
1812     char buf[512];
1813     int xerrno;
1814 
1815     PRIVS_ROOT
1816     fh = fopen(PR_FTPUSERS_PATH, "r");
1817     xerrno = errno;
1818     PRIVS_RELINQUISH
1819 
1820     if (fh == NULL) {
1821       pr_trace_msg(trace_channel, 14,
1822         "error opening '%s' for checking user '%s': %s", PR_FTPUSERS_PATH,
1823         user, strerror(xerrno));
1824       return res;
1825     }
1826 
1827     memset(buf, '\0', sizeof(buf));
1828 
1829     while (fgets(buf, sizeof(buf)-1, fh) != NULL) {
1830       char *ptr;
1831 
1832       pr_signals_handle();
1833 
1834       buf[sizeof(buf)-1] = '\0';
1835       CHOP(buf);
1836 
1837       ptr = buf;
1838       while (PR_ISSPACE(*ptr) && *ptr) {
1839         ptr++;
1840       }
1841 
1842       if (!*ptr ||
1843           *ptr == '#') {
1844         continue;
1845       }
1846 
1847       if (strcmp(ptr, user) == 0 ) {
1848         res = TRUE;
1849         break;
1850       }
1851 
1852       memset(buf, '\0', sizeof(buf));
1853     }
1854 
1855     fclose(fh);
1856   }
1857 
1858   return res;
1859 }
1860 
pr_auth_is_valid_shell(xaset_t * ctx,const char * shell)1861 int pr_auth_is_valid_shell(xaset_t *ctx, const char *shell) {
1862   int res = TRUE;
1863   unsigned char *require_valid_shell;
1864 
1865   if (shell == NULL) {
1866     return res;
1867   }
1868 
1869   require_valid_shell = get_param_ptr(ctx, "RequireValidShell", FALSE);
1870 
1871   if (require_valid_shell == NULL ||
1872       *require_valid_shell == TRUE) {
1873     FILE *fh = NULL;
1874     char buf[256];
1875 
1876     fh = fopen(PR_VALID_SHELL_PATH, "r");
1877     if (fh == NULL) {
1878       return res;
1879     }
1880 
1881     res = FALSE;
1882     memset(buf, '\0', sizeof(buf));
1883 
1884     while (fgets(buf, sizeof(buf)-1, fh) != NULL) {
1885       pr_signals_handle();
1886 
1887       buf[sizeof(buf)-1] = '\0';
1888       CHOP(buf);
1889 
1890       if (strcmp(buf, shell) == 0) {
1891         res = TRUE;
1892         break;
1893       }
1894 
1895       memset(buf, '\0', sizeof(buf));
1896     }
1897 
1898     fclose(fh);
1899   }
1900 
1901   return res;
1902 }
1903 
pr_auth_chroot(const char * path)1904 int pr_auth_chroot(const char *path) {
1905   int res, xerrno = 0;
1906   time_t now;
1907   char *tz = NULL;
1908   const char *default_tz;
1909   pool *tmp_pool;
1910   pr_error_t *err = NULL;
1911 
1912   if (path == NULL) {
1913     errno = EINVAL;
1914     return -1;
1915   }
1916 
1917 #if defined(__GLIBC__) && \
1918     defined(__GLIBC_MINOR__) && \
1919     __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3
1920   default_tz = tzname[0];
1921 #else
1922   /* Per the tzset(3) man page, this should be the assumed default. */
1923   default_tz = ":/etc/localtime";
1924 #endif
1925 
1926   tz = pr_env_get(session.pool, "TZ");
1927   if (tz == NULL) {
1928     if (pr_env_set(session.pool, "TZ", pstrdup(permanent_pool,
1929         default_tz)) < 0) {
1930       pr_log_debug(DEBUG0, "error setting TZ environment variable to "
1931         "'%s': %s", default_tz, strerror(errno));
1932 
1933     } else {
1934       pr_log_debug(DEBUG10, "set TZ environment variable to '%s'", default_tz);
1935     }
1936 
1937   } else {
1938     pr_log_debug(DEBUG10, "TZ environment variable already set to '%s'", tz);
1939   }
1940 
1941   pr_log_debug(DEBUG1, "Preparing to chroot to directory '%s'", path);
1942 
1943   /* Prepare for chroots and the ensuing timezone chicanery by calling
1944    * our pr_localtime() routine now, which will cause libc (via localtime(2))
1945    * to load the tzinfo data into memory, and hopefully retain it (Bug#3431).
1946    */
1947   tmp_pool = make_sub_pool(session.pool);
1948   now = time(NULL);
1949   (void) pr_localtime(tmp_pool, &now);
1950 
1951   pr_event_generate("core.chroot", path);
1952 
1953   PRIVS_ROOT
1954   res = pr_fsio_chroot_with_error(tmp_pool, path, &err);
1955   xerrno = errno;
1956   PRIVS_RELINQUISH
1957 
1958   if (res < 0) {
1959     pr_error_set_where(err, NULL, __FILE__, __LINE__ - 5);
1960     pr_error_set_why(err, pstrcat(tmp_pool, "chroot to directory '", path,
1961       "'", NULL));
1962 
1963     if (err != NULL) {
1964       pr_log_pri(PR_LOG_ERR, "%s", pr_error_strerror(err, 0));
1965       pr_error_destroy(err);
1966       err = NULL;
1967 
1968     } else {
1969       pr_log_pri(PR_LOG_ERR, "chroot to '%s' failed for user '%s': %s", path,
1970         session.user ? session.user : "(unknown)", strerror(xerrno));
1971     }
1972 
1973     destroy_pool(tmp_pool);
1974     errno = xerrno;
1975     return -1;
1976   }
1977 
1978   pr_log_debug(DEBUG1, "Environment successfully chroot()ed");
1979   destroy_pool(tmp_pool);
1980   return 0;
1981 }
1982 
set_groups(pool * p,gid_t primary_gid,array_header * suppl_gids)1983 int set_groups(pool *p, gid_t primary_gid, array_header *suppl_gids) {
1984   int res = 0;
1985   pool *tmp_pool = NULL;
1986 
1987 #ifdef HAVE_SETGROUPS
1988   register unsigned int i = 0;
1989   gid_t *gids = NULL, *proc_gids = NULL;
1990   size_t ngids = 0, nproc_gids = 0;
1991   char *strgids = "";
1992   int have_root_privs = TRUE;
1993 
1994   /* First, check to see whether we even CAN set the process GIDs, which
1995    * requires root privileges.
1996    */
1997   if (getuid() != PR_ROOT_UID) {
1998     have_root_privs = FALSE;
1999   }
2000 
2001   if (have_root_privs == FALSE) {
2002     pr_trace_msg(trace_channel, 3,
2003       "unable to set groups due to lack of root privs");
2004     errno = ENOSYS;
2005     return -1;
2006   }
2007 
2008   /* sanity check */
2009   if (p == NULL ||
2010       suppl_gids == NULL) {
2011 
2012 # ifndef PR_DEVEL_COREDUMP
2013     /* Set the primary GID of the process. */
2014     res = setgid(primary_gid);
2015 # endif /* PR_DEVEL_COREDUMP */
2016 
2017     return res;
2018   }
2019 
2020   ngids = suppl_gids->nelts;
2021   gids = suppl_gids->elts;
2022 
2023   if (ngids == 0 ||
2024       gids == NULL) {
2025     /* No supplemental GIDs to process. */
2026 
2027 # ifndef PR_DEVEL_COREDUMP
2028     /* Set the primary GID of the process. */
2029     res = setgid(primary_gid);
2030 # endif /* PR_DEVEL_COREDUMP */
2031 
2032     return res;
2033   }
2034 
2035   tmp_pool = make_sub_pool(p);
2036   pr_pool_tag(tmp_pool, "set_groups() tmp pool");
2037 
2038   proc_gids = pcalloc(tmp_pool, sizeof(gid_t) * (ngids));
2039 
2040   /* Note: the list of supplemental GIDs may contain duplicates.  Sort
2041    * through the list and keep only the unique IDs - this should help avoid
2042    * running into the NGROUPS limit when possible.  This algorithm may slow
2043    * things down some; optimize it if/when possible.
2044    */
2045   proc_gids[nproc_gids++] = gids[0];
2046 
2047   for (i = 1; i < ngids; i++) {
2048     register unsigned int j = 0;
2049     unsigned char skip_gid = FALSE;
2050 
2051     /* This duplicate ID search only needs to be done after the first GID
2052      * in the given list is examined, as the first GID cannot be a duplicate.
2053      */
2054     for (j = 0; j < nproc_gids; j++) {
2055       if (proc_gids[j] == gids[i]) {
2056         skip_gid = TRUE;
2057         break;
2058       }
2059     }
2060 
2061     if (!skip_gid) {
2062       proc_gids[nproc_gids++] = gids[i];
2063     }
2064   }
2065 
2066   for (i = 0; i < nproc_gids; i++) {
2067     char buf[64];
2068     pr_snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long) proc_gids[i]);
2069     buf[sizeof(buf)-1] = '\0';
2070 
2071     strgids = pstrcat(p, strgids, i != 0 ? ", " : "", buf, NULL);
2072   }
2073 
2074   pr_log_debug(DEBUG10, "setting group %s: %s", nproc_gids == 1 ? "ID" : "IDs",
2075     strgids);
2076 
2077   /* Set the supplemental groups. */
2078   res = setgroups(nproc_gids, proc_gids);
2079   if (res < 0) {
2080     int xerrno = errno;
2081 
2082     destroy_pool(tmp_pool);
2083 
2084     errno = xerrno;
2085     return res;
2086   }
2087 #endif /* !HAVE_SETGROUPS */
2088 
2089 #ifndef PR_DEVEL_COREDUMP
2090   /* Set the primary GID of the process. */
2091   res = setgid(primary_gid);
2092   if (res < 0) {
2093     int xerrno = errno;
2094 
2095     if (tmp_pool != NULL) {
2096       destroy_pool(tmp_pool);
2097     }
2098 
2099     errno = xerrno;
2100     return res;
2101   }
2102 #endif /* PR_DEVEL_COREDUMP */
2103 
2104   if (tmp_pool != NULL) {
2105     destroy_pool(tmp_pool);
2106   }
2107 
2108   return res;
2109 }
2110 
pr_auth_cache_clear(void)2111 void pr_auth_cache_clear(void) {
2112   if (auth_tab != NULL) {
2113     pr_table_empty(auth_tab);
2114     pr_table_free(auth_tab);
2115     auth_tab = NULL;
2116   }
2117 
2118   if (uid_tab != NULL) {
2119     pr_table_empty(uid_tab);
2120     pr_table_free(uid_tab);
2121     uid_tab = NULL;
2122   }
2123 
2124   if (user_tab != NULL) {
2125     pr_table_empty(user_tab);
2126     pr_table_free(user_tab);
2127     user_tab = NULL;
2128   }
2129 
2130   if (gid_tab != NULL) {
2131     pr_table_empty(gid_tab);
2132     pr_table_free(gid_tab);
2133     gid_tab = NULL;
2134   }
2135 
2136   if (group_tab != NULL) {
2137     pr_table_empty(group_tab);
2138     pr_table_free(group_tab);
2139     group_tab = NULL;
2140   }
2141 }
2142 
pr_auth_cache_set(int enable,unsigned int flags)2143 int pr_auth_cache_set(int enable, unsigned int flags) {
2144   if (enable != FALSE &&
2145       enable != TRUE) {
2146     errno = EINVAL;
2147     return -1;
2148   }
2149 
2150   if (enable == FALSE) {
2151     if (flags & PR_AUTH_CACHE_FL_UID2NAME) {
2152       auth_caching &= ~PR_AUTH_CACHE_FL_UID2NAME;
2153       pr_trace_msg(trace_channel, 7, "UID-to-name caching (uidcache) disabled");
2154     }
2155 
2156     if (flags & PR_AUTH_CACHE_FL_GID2NAME) {
2157       auth_caching &= ~PR_AUTH_CACHE_FL_GID2NAME;
2158       pr_trace_msg(trace_channel, 7, "GID-to-name caching (gidcache) disabled");
2159     }
2160 
2161     if (flags & PR_AUTH_CACHE_FL_AUTH_MODULE) {
2162       auth_caching &= ~PR_AUTH_CACHE_FL_AUTH_MODULE;
2163       pr_trace_msg(trace_channel, 7,
2164         "auth module caching (authcache) disabled");
2165     }
2166 
2167     if (flags & PR_AUTH_CACHE_FL_NAME2UID) {
2168       auth_caching &= ~PR_AUTH_CACHE_FL_NAME2UID;
2169       pr_trace_msg(trace_channel, 7,
2170         "name-to-UID caching (usercache) disabled");
2171     }
2172 
2173     if (flags & PR_AUTH_CACHE_FL_NAME2GID) {
2174       auth_caching &= ~PR_AUTH_CACHE_FL_NAME2GID;
2175       pr_trace_msg(trace_channel, 7,
2176         "name-to-GID caching (groupcache) disabled");
2177     }
2178 
2179     if (flags & PR_AUTH_CACHE_FL_BAD_UID2NAME) {
2180       auth_caching &= ~PR_AUTH_CACHE_FL_BAD_UID2NAME;
2181       pr_trace_msg(trace_channel, 7,
2182         "UID-to-name negative caching (uidcache) disabled");
2183     }
2184 
2185     if (flags & PR_AUTH_CACHE_FL_BAD_GID2NAME) {
2186       auth_caching &= ~PR_AUTH_CACHE_FL_BAD_GID2NAME;
2187       pr_trace_msg(trace_channel, 7,
2188         "GID-to-name negative caching (gidcache) disabled");
2189     }
2190 
2191     if (flags & PR_AUTH_CACHE_FL_BAD_NAME2UID) {
2192       auth_caching &= ~PR_AUTH_CACHE_FL_BAD_NAME2UID;
2193       pr_trace_msg(trace_channel, 7,
2194         "name-to-UID negative caching (usercache) disabled");
2195     }
2196 
2197     if (flags & PR_AUTH_CACHE_FL_BAD_NAME2GID) {
2198       auth_caching &= ~PR_AUTH_CACHE_FL_BAD_NAME2GID;
2199       pr_trace_msg(trace_channel, 7,
2200         "name-to-GID negative caching (groupcache) disabled");
2201     }
2202   }
2203 
2204   if (enable == TRUE) {
2205     if (flags & PR_AUTH_CACHE_FL_UID2NAME) {
2206       auth_caching |= PR_AUTH_CACHE_FL_UID2NAME;
2207       pr_trace_msg(trace_channel, 7, "UID-to-name caching (uidcache) enabled");
2208     }
2209 
2210     if (flags & PR_AUTH_CACHE_FL_GID2NAME) {
2211       auth_caching |= PR_AUTH_CACHE_FL_GID2NAME;
2212       pr_trace_msg(trace_channel, 7, "GID-to-name caching (gidcache) enabled");
2213     }
2214 
2215     if (flags & PR_AUTH_CACHE_FL_AUTH_MODULE) {
2216       auth_caching |= PR_AUTH_CACHE_FL_AUTH_MODULE;
2217       pr_trace_msg(trace_channel, 7, "auth module caching (authcache) enabled");
2218     }
2219 
2220     if (flags & PR_AUTH_CACHE_FL_NAME2UID) {
2221       auth_caching |= PR_AUTH_CACHE_FL_NAME2UID;
2222       pr_trace_msg(trace_channel, 7, "name-to-UID caching (usercache) enabled");
2223     }
2224 
2225     if (flags & PR_AUTH_CACHE_FL_NAME2GID) {
2226       auth_caching |= PR_AUTH_CACHE_FL_NAME2GID;
2227       pr_trace_msg(trace_channel, 7,
2228         "name-to-GID caching (groupcache) enabled");
2229     }
2230 
2231     if (flags & PR_AUTH_CACHE_FL_BAD_UID2NAME) {
2232       auth_caching |= PR_AUTH_CACHE_FL_BAD_UID2NAME;
2233       pr_trace_msg(trace_channel, 7,
2234         "UID-to-name negative caching (uidcache) enabled");
2235     }
2236 
2237     if (flags & PR_AUTH_CACHE_FL_BAD_GID2NAME) {
2238       auth_caching |= PR_AUTH_CACHE_FL_BAD_GID2NAME;
2239       pr_trace_msg(trace_channel, 7,
2240         "GID-to-name negative caching (gidcache) enabled");
2241     }
2242 
2243     if (flags & PR_AUTH_CACHE_FL_BAD_NAME2UID) {
2244       auth_caching |= PR_AUTH_CACHE_FL_BAD_NAME2UID;
2245       pr_trace_msg(trace_channel, 7,
2246         "name-to-UID negative caching (usercache) enabled");
2247     }
2248 
2249     if (flags & PR_AUTH_CACHE_FL_BAD_NAME2GID) {
2250       auth_caching |= PR_AUTH_CACHE_FL_BAD_NAME2GID;
2251       pr_trace_msg(trace_channel, 7,
2252         "name-to-GID negative caching (groupcache) enabled");
2253     }
2254   }
2255 
2256   return 0;
2257 }
2258 
pr_auth_add_auth_only_module(const char * name)2259 int pr_auth_add_auth_only_module(const char *name) {
2260   struct auth_module_elt *elt = NULL;
2261 
2262   if (name == NULL) {
2263     errno = EINVAL;
2264     return -1;
2265   }
2266 
2267   if (auth_pool == NULL) {
2268     auth_pool = make_sub_pool(permanent_pool);
2269     pr_pool_tag(auth_pool, "Auth API");
2270   }
2271 
2272   if (!(auth_caching & PR_AUTH_CACHE_FL_AUTH_MODULE)) {
2273     /* We won't be using the auth-only module cache, so there's no need to
2274      * accept this.
2275      */
2276     pr_trace_msg(trace_channel, 9, "not adding '%s' to the auth-only list: "
2277       "caching of auth-only modules disabled", name);
2278     return 0;
2279   }
2280 
2281   if (auth_module_list == NULL) {
2282     auth_module_list = xaset_create(auth_pool, NULL);
2283   }
2284 
2285   /* Prevent duplicates; they could lead to a memory leak. */
2286   for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt;
2287       elt = elt->next) {
2288     if (strcmp(elt->name, name) == 0) {
2289       errno = EEXIST;
2290       return -1;
2291     }
2292   }
2293 
2294   elt = pcalloc(auth_pool, sizeof(struct auth_module_elt));
2295   elt->name = pstrdup(auth_pool, name);
2296 
2297   if (xaset_insert_end(auth_module_list, (xasetmember_t *) elt) < 0) {
2298     pr_trace_msg(trace_channel, 1, "error adding '%s' to auth-only "
2299       "module set: %s", name, strerror(errno));
2300     return -1;
2301   }
2302 
2303   pr_trace_msg(trace_channel, 5, "added '%s' to auth-only module list", name);
2304   return 0;
2305 }
2306 
pr_auth_clear_auth_only_modules(void)2307 int pr_auth_clear_auth_only_modules(void) {
2308   if (auth_module_list == NULL) {
2309     errno = EPERM;
2310     return -1;
2311   }
2312 
2313   auth_module_list = NULL;
2314   pr_trace_msg(trace_channel, 5, "cleared auth-only module list");
2315   return 0;
2316 }
2317 
pr_auth_remove_auth_only_module(const char * name)2318 int pr_auth_remove_auth_only_module(const char *name) {
2319   struct auth_module_elt *elt = NULL;
2320 
2321   if (name == NULL) {
2322     errno = EINVAL;
2323     return -1;
2324   }
2325 
2326   if (!(auth_caching & PR_AUTH_CACHE_FL_AUTH_MODULE)) {
2327     /* We won't be using the auth-only module cache, so there's no need to
2328      * accept this.
2329      */
2330     pr_trace_msg(trace_channel, 9, "not removing '%s' from the auth-only list: "
2331       "caching of auth-only modules disabled", name);
2332     return 0;
2333   }
2334 
2335   if (auth_module_list == NULL) {
2336     pr_trace_msg(trace_channel, 9, "not removing '%s' from list: "
2337       "empty auth-only module list", name);
2338     errno = EPERM;
2339     return -1;
2340   }
2341 
2342   for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt;
2343       elt = elt->next) {
2344     if (strcmp(elt->name, name) == 0) {
2345       if (xaset_remove(auth_module_list, (xasetmember_t *) elt) < 0) {
2346         pr_trace_msg(trace_channel, 1, "error removing '%s' from auth-only "
2347           "module set: %s", name, strerror(errno));
2348         return -1;
2349       }
2350 
2351       pr_trace_msg(trace_channel, 5, "removed '%s' from auth-only module list",
2352         name);
2353       return 0;
2354     }
2355   }
2356 
2357   errno = ENOENT;
2358   return -1;
2359 }
2360 
pr_auth_get_home(pool * p,const char * pw_dir)2361 const char *pr_auth_get_home(pool *p, const char *pw_dir) {
2362   config_rec *c;
2363   const char *home_dir;
2364 
2365   if (p == NULL ||
2366       pw_dir == NULL) {
2367     errno = EINVAL;
2368     return NULL;
2369   }
2370 
2371   home_dir = pw_dir;
2372 
2373   c = find_config(main_server->conf, CONF_PARAM, "RewriteHome", FALSE);
2374   if (c == NULL) {
2375     return home_dir;
2376   }
2377 
2378   if (*((int *) c->argv[0]) == FALSE) {
2379     return home_dir;
2380   }
2381 
2382   /* Rather than using a cmd_rec dispatched to mod_rewrite's PRE_CMD handler,
2383    * we use an approach with looser coupling to mod_rewrite: stash the
2384    * home directory in the session.notes table, and generate an event.
2385    * The mod_rewrite module will listen for this event, rewrite the stashed
2386    * home directory as necessary, and be done.
2387    *
2388    * Thus after the event has been generated, we retrieve (and remove) the
2389    * (possibly rewritten) home directory from the session.notes table.
2390    * This approach means that other modules which wish to get involved
2391    * in the rewriting of the home directory can also do so.
2392    */
2393 
2394   (void) pr_table_remove(session.notes, "mod_auth.home-dir", NULL);
2395   if (pr_table_add(session.notes, "mod_auth.home-dir",
2396       pstrdup(p, pw_dir), 0) < 0) {
2397     pr_trace_msg(trace_channel, 3,
2398       "error stashing home dir in session.notes: %s", strerror(errno));
2399     return home_dir;
2400   }
2401 
2402   pr_event_generate("mod_auth.rewrite-home", NULL);
2403 
2404   home_dir = pr_table_get(session.notes, "mod_auth.home-dir", NULL);
2405   if (home_dir == NULL) {
2406     pr_trace_msg(trace_channel, 3,
2407       "error getting home dir from session.notes: %s", strerror(errno));
2408     return pw_dir;
2409   }
2410 
2411   (void) pr_table_remove(session.notes, "mod_auth.home-dir", NULL);
2412 
2413   pr_log_debug(DEBUG9, "returning rewritten home directory '%s' for original "
2414     "home directory '%s'", home_dir, pw_dir);
2415   pr_trace_msg(trace_channel, 9, "returning rewritten home directory '%s' "
2416     "for original home directory '%s'", home_dir, pw_dir);
2417 
2418   return home_dir;
2419 }
2420 
pr_auth_set_max_password_len(pool * p,size_t len)2421 size_t pr_auth_set_max_password_len(pool *p, size_t len) {
2422   size_t prev_len;
2423 
2424   prev_len = auth_max_passwd_len;
2425 
2426   if (len == 0) {
2427     /* Restore default. */
2428     auth_max_passwd_len = PR_TUNABLE_PASSWORD_MAX;
2429 
2430   } else {
2431     auth_max_passwd_len = len;
2432   }
2433 
2434   return prev_len;
2435 }
2436 
pr_auth_bcrypt(pool * p,const char * key,const char * salt,size_t * hashed_len)2437 char *pr_auth_bcrypt(pool *p, const char *key, const char *salt,
2438     size_t *hashed_len) {
2439   char hashed[128], *res;
2440 
2441   if (p == NULL ||
2442       key == NULL ||
2443       salt == NULL ||
2444       hashed_len == NULL) {
2445     errno = EINVAL;
2446     return NULL;
2447   }
2448 
2449   if (bcrypt_hashpass(key, salt, hashed, sizeof(hashed)) != 0) {
2450     return NULL;
2451   }
2452 
2453   res = palloc(p, sizeof(hashed));
2454   memcpy(res, hashed, sizeof(hashed));
2455   *hashed_len = sizeof(hashed);
2456 
2457   return res;
2458 }
2459 
2460 /* Internal use only.  To be called in the session process. */
init_auth(void)2461 int init_auth(void) {
2462   if (auth_pool == NULL) {
2463     auth_pool = make_sub_pool(permanent_pool);
2464     pr_pool_tag(auth_pool, "Auth API");
2465   }
2466 
2467   return 0;
2468 }
2469