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