Coverage Report

Created: 2024-09-08 06:03

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