summaryrefslogtreecommitdiff
path: root/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
blob: cd93ded426559da4156eae5b08d137aaf5775c6d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * $Id: modutil_getpwuid.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
 *
 * This function provides a thread safer version of getpwuid() for use
 * with PAM modules that care about this sort of thing.
 *
 * XXX - or at least it should provide a thread-safe alternative.
 */

#include "pammodutil.h"

#include <pwd.h>
#include <stdlib.h>

struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
{
#ifdef HAVE_GETPWNAM_R

    void *buffer=NULL;
    size_t length = PWD_INITIAL_LENGTH;

    do {
	int status;
	void *new_buffer;
	struct passwd *result = NULL;

	new_buffer = realloc(buffer, sizeof(struct passwd) + length);
	if (new_buffer == NULL) {

	    D(("out of memory"));

	    /* no memory for the user - so delete the memory */
	    if (buffer) {
		free(buffer);
	    }
	    return NULL;
	}
	buffer = new_buffer;

	/* make the re-entrant call to get the pwd structure */
	status = getpwuid_r(uid, buffer,
			    sizeof(struct passwd) + (char *) buffer,
			    length, &result);
	if (!status && result) {
	    status = pam_set_data(pamh, "_pammodutil_getpwuid", result,
				  _pammodutil_cleanup);
	    if (status == PAM_SUCCESS) {
		D(("success"));
		return result;
	    }

	    D(("was unable to register the data item [%s]",
	       pam_strerror(pamh, status)));

	    free(buffer);
	    return NULL;

	}
	
	length <<= 1;

    } while (length < PWD_ABSURD_PWD_LENGTH);

    D(("pwd structure took %u bytes or so of memory",
       length+sizeof(struct passwd)));

    free(buffer);
    return NULL;

#else /* ie. ifndef HAVE_GETPWNAM_R */

    /*
     * Sorry, there does not appear to be a reentrant version of
     * getpwnam(). So, we use the standard libc function.
     */
    
    return getpwuid(uid);

#endif /* def HAVE_GETPWNAM_R */
}