]> granicus.if.org Git - linux-pam/blob - modules/pammodutil/modutil_getpwnam.c
287dc0654f551f63d7b12e8d521c80ecd9f30344
[linux-pam] / modules / pammodutil / modutil_getpwnam.c
1 /*
2  * $Id$
3  *
4  * This function provides a thread safer version of getpwnam() for use
5  * with PAM modules that care about this sort of thing.
6  *
7  * XXX - or at least it should provide a thread-safe alternative.
8  */
9
10 #include "pammodutil.h"
11
12 #include <pwd.h>
13 #include <stdlib.h>
14
15 struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
16 {
17 #ifdef HAVE_GETPWNAM_R
18
19     void *buffer=NULL;
20     size_t length = PWD_INITIAL_LENGTH;
21
22     do {
23         int status;
24         void *new_buffer;
25         struct passwd *result = NULL;
26
27         new_buffer = realloc(buffer, sizeof(struct passwd) + length);
28         if (new_buffer == NULL) {
29
30             D(("out of memory"));
31
32             /* no memory for the user - so delete the memory */
33             if (buffer) {
34                 free(buffer);
35             }
36             return NULL;
37         }
38         buffer = new_buffer;
39
40         /* make the re-entrant call to get the pwd structure */
41         status = getpwnam_r(user, buffer,
42                             sizeof(struct passwd) + (char *) buffer,
43                             length, &result);
44         if (!status && result) {
45             status = pam_set_data(pamh, "_pammodutil_getpwnam", result,
46                                   _pammodutil_cleanup);
47             if (status == PAM_SUCCESS) {
48                 D(("success"));
49                 return result;
50             }
51
52             D(("was unable to register the data item [%s]",
53                pam_strerror(pamh, status)));
54
55             free(buffer);
56             return NULL;
57
58         }
59         
60         length <<= 1;
61
62     } while (length < PWD_ABSURD_PWD_LENGTH);
63
64     D(("pwd structure took %u bytes or so of memory",
65        length+sizeof(struct passwd)));
66
67     free(buffer);
68     return NULL;
69
70 #else /* ie. ifndef HAVE_GETPWNAM_R */
71
72     /*
73      * Sorry, there does not appear to be a reentrant version of
74      * getpwnam(). So, we use the standard libc function.
75      */
76     
77     return getpwnam(user);
78
79 #endif /* def HAVE_GETPWNAM_R */
80 }