2 * $Id: uams_passwd.c,v 1.31 2010-03-30 12:44:35 franklahm Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
6 * All Rights Reserved. See COPYRIGHT.
11 #endif /* HAVE_CONFIG_H */
13 #include <sys/types.h>
14 /* crypt needs _XOPEN_SOURCE (500) at least on BSD, but that breaks Solaris compile */
16 #define _XOPEN_SOURCE 500 /* for crypt() */
19 #define _XOPEN_SOURCE /* for crypt() */
27 #else /* STDC_HEADERS */
31 #endif /* HAVE_STRCHR */
32 char *strchr (), *strrchr ();
34 #define memcpy(d,s,n) bcopy ((s), (d), (n))
35 #define memmove(d,s,n) bcopy ((s), (d), (n))
36 #endif /* ! HAVE_MEMCPY */
37 #endif /* STDC_HEADERS */
40 #endif /* HAVE_UNISTD_H */
43 #endif /* ! HAVE_CRYPT_H */
45 #ifdef HAVE_SYS_TIME_H
55 #include <atalk/afp.h>
56 #include <atalk/logger.h>
57 #include <atalk/uam.h>
58 #include <atalk/util.h>
63 #define MIN(a,b) ((a) < (b) ? (a) : (b))
71 static const char *clientname;
74 /*XXX in etc/papd/file.h */
76 extern UAM_MODULE_EXPORT void append(struct papfile *, const char *, int);
78 static int pwd_login(void *obj, char *username, int ulen, struct passwd **uam_pwd,
79 char *ibuf, size_t ibuflen,
80 char *rbuf _U_, size_t *rbuflen _U_)
90 if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME,
91 (void *) &clientname, NULL ) < 0 )
95 if (ibuflen < PASSWDLEN) {
96 return( AFPERR_PARAM );
98 ibuf[ PASSWDLEN ] = '\0';
100 if (( pwd = uam_getname(obj, username, ulen)) == NULL ) {
101 return AFPERR_NOTAUTH;
104 LOG(log_info, logtype_uams, "cleartext login: %s", username);
106 if (uam_checkuser(pwd) < 0) {
107 LOG(log_info, logtype_uams, "not a valid user");
108 return AFPERR_NOTAUTH;
112 if (( sp = getspnam( pwd->pw_name )) == NULL ) {
113 LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username);
114 return AFPERR_NOTAUTH;
116 pwd->pw_passwd = sp->sp_pwdp;
118 if (sp && sp->sp_max != -1 && sp->sp_lstchg) {
119 time_t now = time(NULL) / (60*60*24);
120 int32_t expire_days = sp->sp_lstchg - now + sp->sp_max;
121 if ( expire_days < 0 ) {
122 LOG(log_info, logtype_uams, "Password for user %s expired", username);
123 err = AFPERR_PWDEXPR;
126 #endif /* SHADOWPW */
128 if (!pwd->pw_passwd) {
129 return AFPERR_NOTAUTH;
140 uam_afp_getcmdline( &ac, &av );
141 sprintf( hostname, "%s@%s", username, clientname );
143 if( uam_sia_validate_user( NULL, ac, av, hostname, username,
144 NULL, FALSE, NULL, ibuf ) != SIASUCCESS )
145 return AFPERR_NOTAUTH;
150 p = crypt( ibuf, pwd->pw_passwd );
151 if ( strcmp( p, pwd->pw_passwd ) == 0 )
155 return AFPERR_NOTAUTH;
160 static int passwd_login(void *obj, struct passwd **uam_pwd,
161 char *ibuf, size_t ibuflen,
162 char *rbuf, size_t *rbuflen)
169 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
170 (void *) &username, &ulen) < 0)
174 return( AFPERR_PARAM );
177 len = (unsigned char) *ibuf++;
179 if (!len || len > ibuflen || len > ulen ) {
180 return( AFPERR_PARAM );
182 memcpy(username, ibuf, len );
185 username[ len ] = '\0';
187 if ((unsigned long) ibuf & 1) { /* pad character */
191 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
195 /* cleartxt login ext
198 2 bytes len (network order)
199 len bytes unicode name
201 static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
202 char *ibuf, size_t ibuflen,
203 char *rbuf, size_t *rbuflen)
211 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
212 (void *) &username, &ulen) < 0)
218 memcpy(&temp16, uname, sizeof(temp16));
220 if (!len || len > ulen ) {
221 return( AFPERR_PARAM );
223 memcpy(username, uname +2, len );
224 username[ len ] = '\0';
225 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
231 static int passwd_changepw(void *obj, char *username,
232 struct passwd *pwd, char *ibuf,
233 size_t ibuflen, char *rbuf, size_t *rbuflen)
237 #endif /* SHADOWPW */
238 char pw[PASSWDLEN + 1], *p;
239 uid_t uid = geteuid();
241 if (uam_checkuser(pwd) < 0)
242 return AFPERR_ACCESS;
245 memcpy(pw, ibuf, PASSWDLEN);
246 memset(ibuf, 0, PASSWDLEN);
247 pw[PASSWDLEN] = '\0';
250 if (( sp = getspnam( pwd->pw_name )) == NULL ) {
251 LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username);
254 pwd->pw_passwd = sp->sp_pwdp;
255 #endif /* SHADOWPW */
257 p = crypt(pw, pwd->pw_passwd );
258 if (strcmp( p, pwd->pw_passwd )) {
259 memset(pw, 0, sizeof(pw));
260 return AFPERR_NOTAUTH;
265 ibuf[PASSWDLEN] = '\0';
269 #endif /* SHADOWPW */
275 /* Printer ClearTxtUAM login */
276 static int passwd_printer(char *start, char *stop, char *username, struct papfile *out)
281 #endif /* SHADOWPW */
283 char password[PASSWDLEN + 1] = "\0";
284 static const char *loginok = "0\r";
287 data = (char *)malloc(stop - start + 1);
289 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: malloc");
292 strlcpy(data, start, stop - start + 1);
294 /* We are looking for the following format in data:
295 * (username) (password)
297 * Let's hope username doesn't contain ") ("!
300 /* Parse input for username in () */
301 if ((p = strchr(data, '(' )) == NULL) {
302 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string");
307 if ((q = strstr(p, ") (" )) == NULL) {
308 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string");
312 memcpy(username, p, MIN( UAM_USERNAMELEN, q - p ));
314 /* Parse input for password in next () */
316 if ((q = strrchr(p , ')' )) == NULL) {
317 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: password not found in string");
321 memcpy(password, p, MIN(PASSWDLEN, q - p) );
323 /* Done copying username and password, clean up */
326 ulen = strlen(username);
328 if (( pwd = uam_getname(NULL, username, ulen)) == NULL ) {
329 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: ( %s ) not found ",
334 if (uam_checkuser(pwd) < 0) {
335 /* syslog of error happens in uam_checkuser */
340 if (( sp = getspnam( pwd->pw_name )) == NULL ) {
341 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no shadow passwd entry for %s",
345 pwd->pw_passwd = sp->sp_pwdp;
347 if (sp && sp->sp_max != -1 && sp->sp_lstchg) {
348 time_t now = time(NULL) / (60*60*24);
349 int32_t expire_days = sp->sp_lstchg - now + sp->sp_max;
350 if ( expire_days < 0 ) {
351 LOG(log_info, logtype_uams, "Password for user %s expired", username);
356 #endif /* SHADOWPW */
358 if (!pwd->pw_passwd) {
359 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no password for %s",
365 if ( kcheckuser( pwd, password) == 0)
369 p = crypt(password, pwd->pw_passwd);
370 if (strcmp(p, pwd->pw_passwd) != 0) {
371 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: bad password", username);
375 /* Login successful */
376 append(out, loginok, strlen(loginok));
377 LOG(log_info, logtype_uams, "Login ClearTxtUAM: %s", username);
381 static int uam_setup(const char *path)
383 if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd",
384 passwd_login, NULL, NULL, passwd_login_ext) < 0)
386 if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM",
393 static void uam_cleanup(void)
395 uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd");
396 uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM");
399 UAM_MODULE_EXPORT struct uam_export uams_clrtxt = {
402 uam_setup, uam_cleanup
405 UAM_MODULE_EXPORT struct uam_export uams_passwd = {
408 uam_setup, uam_cleanup