File: auth.c

package info (click to toggle)
citadel 7.83-2squeeze2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 4,572 kB
  • ctags: 3,756
  • sloc: ansic: 54,870; sh: 4,298; yacc: 660; makefile: 450; xml: 40
file content (154 lines) | stat: -rw-r--r-- 3,695 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
/*
 * $Id: auth.c 7898 2009-10-14 19:20:06Z ajc $
 *
 * system-level password checking for host auth mode
 * by Nathan Bryant, March 1999
 * updated by Trey van Riper, June 2005
 *
 * Copyright (c) 1999-2009 by the citadel.org team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#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)
{
#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;
	int flags = 0;

	flags = 0;	/* silences compiler warning */

#ifdef PAM_DATA_SILENT
	flags = ( flags | PAM_DATA_SILENT ) ;
#endif /* PAM_DATA_SILENT */
	if ((pw = getpwuid(uid)) == NULL) {
		return retval;
	}

#ifdef HAVE_PAM_START
	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 retval;

	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 ((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;
}