File: auth.c

package info (click to toggle)
citadel 917-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 3,976 kB
  • sloc: ansic: 44,751; sh: 4,209; yacc: 651; makefile: 399
file content (156 lines) | stat: -rw-r--r-- 3,368 bytes parent folder | download
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * system-level password checking for host auth mode
 * by Nathan Bryant, March 1999
 * updated by Trey van Riper, June 2005
 *
 * Copyright (c) 1999-2016 by the citadel.org team
 *
 * This program is open source software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#if defined(__linux) || defined(__sun) /* needed for crypt(): */
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED 1
#endif

#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#include "auth.h"
#include "sysdep.h"

#ifdef HAVE_GETSPNAM
#include <shadow.h>
#endif

#ifdef HAVE_PAM_START
#include <security/pam_appl.h>

/*
 * struct appdata: passed to the conversation function
 */

struct appdata
{
  const char *name;
  const char *pw;
};

/*
 * conv(): the PAM conversation function. this assumes that a
 * PAM_PROMPT_ECHO_ON is asking for a username, and a PAM_PROMPT_ECHO_OFF is
 * asking for a password. esoteric authentication modules will fail with this
 * code, but we can't really support them with the existing client protocol
 * anyway. the failure mode should be to deny access, in any case.
 */

static int conv(int num_msg, const struct pam_message **msg,
		struct pam_response **resp, void *appdata_ptr)
{
  struct pam_response *temp_resp;
  struct appdata *data = appdata_ptr;

  if ((temp_resp = malloc(sizeof(struct pam_response[num_msg]))) == NULL)
    return PAM_CONV_ERR;

  while (num_msg--)
    {
      switch ((*msg)[num_msg].msg_style)
	{
	case PAM_PROMPT_ECHO_ON:
	  temp_resp[num_msg].resp = strdup(data->name);
	  break;
	case PAM_PROMPT_ECHO_OFF:
	  temp_resp[num_msg].resp = strdup(data->pw);
	  break;
	default:
	  temp_resp[num_msg].resp = NULL;
	}
      temp_resp[num_msg].resp_retcode = 0;
    }

  *resp = temp_resp;
  return PAM_SUCCESS;
}
#endif /* HAVE_PAM_START */


/*
 * check that `pass' is the correct password for `uid'
 * returns zero if no, nonzero if yes
 */

int validate_password(uid_t uid, const char *pass)
{
	if (pass == NULL) {
		return(0);
	}

#ifdef HAVE_PAM_START
	struct pam_conv pc;
	struct appdata data;
	pam_handle_t *ph;
	int i;
#else
	char *crypted_pwd;
#ifdef HAVE_GETSPNAM
	struct spwd *sp;
#endif
#endif
	struct passwd *pw;
	int retval = 0;

	pw = getpwuid(uid);
	if (pw == NULL) {
		return retval;
	}

#ifdef HAVE_PAM_START

#ifdef PAM_DATA_SILENT
	int flags = PAM_DATA_SILENT;
#else
	int flags = 0;
#endif

	pc.conv = conv;
	pc.appdata_ptr = &data;
	data.name = pw->pw_name;
	data.pw = pass;
	if (pam_start("citadel", pw->pw_name, &pc, &ph) != PAM_SUCCESS)
		return(0);

	if ((i = pam_authenticate(ph, flags)) == PAM_SUCCESS) {
		if ((i = pam_acct_mgmt(ph, flags)) == PAM_SUCCESS) {
			retval = -1;
		}
	}

	pam_end(ph, i | flags);
#else
	crypted_pwd = pw->pw_passwd;

#ifdef HAVE_GETSPNAM
	if (pw == NULL) return(0);
	if (pw->pw_name == NULL) return(0);
	if ((sp = getspnam(pw->pw_name)) != NULL) {
		crypted_pwd = sp->sp_pwdp;
	}
#endif

	if (!strcmp(crypt(pass, crypted_pwd), crypted_pwd)) {
		retval = -1;
	}
#endif				/* HAVE_PAM_START */

	return retval;
}