~ubuntu-core-dev/pam/ubuntu

« back to all changes in this revision

Viewing changes to libpam/pam_modutil_getpwnam.c

  • Committer: Steve Langasek
  • Date: 2014-01-16 02:02:59 UTC
  • mfrom: (696.11.134 pam.debian)
  • Revision ID: steve.langasek@canonical.com-20140116020259-w2zltneod077conz
Merge version 1.1.8-1 from Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: pam_modutil_getpwnam.c,v 1.3 2008/05/14 12:55:02 t8m Exp $
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 "pam_modutil_private.h"
11
 
 
12
 
#include <errno.h>
13
 
#include <limits.h>
14
 
#include <pwd.h>
15
 
#include <stdio.h>
16
 
#include <stdlib.h>
17
 
 
18
 
static int intlen(int number)
19
 
20
 
    int len = 2;
21
 
    while (number != 0) {
22
 
        number /= 10;
23
 
        len++;
24
 
    }
25
 
    return len;
26
 
}
27
 
 
28
 
struct passwd *
29
 
pam_modutil_getpwnam(pam_handle_t *pamh, const char *user)
30
 
{
31
 
#ifdef HAVE_GETPWNAM_R
32
 
 
33
 
    void *buffer=NULL;
34
 
    size_t length = PWD_INITIAL_LENGTH;
35
 
 
36
 
    do {
37
 
        int status;
38
 
        void *new_buffer;
39
 
        struct passwd *result = NULL;
40
 
 
41
 
        new_buffer = realloc(buffer, sizeof(struct passwd) + length);
42
 
        if (new_buffer == NULL) {
43
 
 
44
 
            D(("out of memory"));
45
 
 
46
 
            /* no memory for the user - so delete the memory */
47
 
            if (buffer) {
48
 
                free(buffer);
49
 
            }
50
 
            return NULL;
51
 
        }
52
 
        buffer = new_buffer;
53
 
 
54
 
        /* make the re-entrant call to get the pwd structure */
55
 
        errno = 0;
56
 
        status = getpwnam_r(user, buffer,
57
 
                            sizeof(struct passwd) + (char *) buffer,
58
 
                            length, &result);
59
 
        if (!status && (result == buffer)) {
60
 
            char *data_name;
61
 
            const void *ignore;
62
 
            int i;
63
 
 
64
 
            data_name = malloc(strlen("_pammodutil_getpwnam") + 1 +
65
 
                               strlen(user) + 1 + intlen(INT_MAX) + 1);
66
 
            if ((pamh != NULL) && (data_name == NULL)) {
67
 
                D(("was unable to register the data item [%s]",
68
 
                   pam_strerror(pamh, status)));
69
 
                free(buffer);
70
 
                return NULL;
71
 
            }
72
 
 
73
 
            if (pamh != NULL) {
74
 
                for (i = 0; i < INT_MAX; i++) {
75
 
                    sprintf(data_name, "_pammodutil_getpwnam_%s_%d", user, i);
76
 
                    status = PAM_NO_MODULE_DATA;
77
 
                    if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
78
 
                        status = pam_set_data(pamh, data_name,
79
 
                                              result, pam_modutil_cleanup);
80
 
                    }
81
 
                    if (status == PAM_SUCCESS) {
82
 
                        break;
83
 
                    }
84
 
                }
85
 
            } else {
86
 
                status = PAM_SUCCESS;
87
 
            }
88
 
 
89
 
            free(data_name);
90
 
 
91
 
            if (status == PAM_SUCCESS) {
92
 
                D(("success"));
93
 
                return result;
94
 
            }
95
 
 
96
 
            D(("was unable to register the data item [%s]",
97
 
               pam_strerror(pamh, status)));
98
 
 
99
 
            free(buffer);
100
 
            return NULL;
101
 
 
102
 
        } else if (errno != ERANGE && errno != EINTR) {
103
 
                /* no sense in repeating the call */
104
 
                break;
105
 
        }
106
 
        
107
 
        length <<= PWD_LENGTH_SHIFT;
108
 
 
109
 
    } while (length < PWD_ABSURD_PWD_LENGTH);
110
 
 
111
 
    D(("pwd structure took %u bytes or so of memory",
112
 
       length+sizeof(struct passwd)));
113
 
 
114
 
    free(buffer);
115
 
    return NULL;
116
 
 
117
 
#else /* ie. ifndef HAVE_GETPWNAM_R */
118
 
 
119
 
    /*
120
 
     * Sorry, there does not appear to be a reentrant version of
121
 
     * getpwnam(). So, we use the standard libc function.
122
 
     */
123
 
    
124
 
    return getpwnam(user);
125
 
 
126
 
#endif /* def HAVE_GETPWNAM_R */
127
 
}