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