1/* 2 * Copyright (c) 1990,1993 Regents of The University of Michigan. 3 * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 4 * All Rights Reserved. See COPYRIGHT. 5 */ 6 7#ifdef HAVE_CONFIG_H 8#include <config.h> 9#endif /* HAVE_CONFIG_H */ 10 11#include <atalk/standards.h> 12 13#include <sys/types.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <unistd.h> 18#ifdef HAVE_CRYPT_H 19#include <crypt.h> 20#endif /* ! HAVE_CRYPT_H */ 21#include <pwd.h> 22#include <sys/time.h> 23#include <time.h> 24#ifdef SHADOWPW 25#include <shadow.h> 26#endif /* SHADOWPW */ 27#include <arpa/inet.h> 28 29#include <atalk/afp.h> 30#include <atalk/logger.h> 31#include <atalk/uam.h> 32#include <atalk/util.h> 33#include <atalk/compat.h> 34 35#define PASSWDLEN 8 36 37#ifndef MIN 38#define MIN(a,b) ((a) < (b) ? (a) : (b)) 39#endif /* MIN */ 40 41 42#ifdef TRU64 43#include <sia.h> 44#include <siad.h> 45 46static const char *clientname; 47#endif /* TRU64 */ 48 49/*XXX in etc/papd/file.h */ 50struct papfile; 51extern UAM_MODULE_EXPORT void append(struct papfile *, const char *, int); 52 53static int pwd_login(void *obj, char *username, int ulen, struct passwd **uam_pwd, 54 char *ibuf, size_t ibuflen, 55 char *rbuf _U_, size_t *rbuflen _U_) 56{ 57 char *p; 58 struct passwd *pwd; 59 int err = AFP_OK; 60#ifdef SHADOWPW 61 struct spwd *sp; 62#endif /* SHADOWPW */ 63 64#ifdef TRU64 65 if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME, 66 (void *) &clientname, NULL ) < 0 ) 67 return AFPERR_MISC; 68#endif /* TRU64 */ 69 70 if (ibuflen < PASSWDLEN) { 71 return( AFPERR_PARAM ); 72 } 73 ibuf[ PASSWDLEN ] = '\0'; 74 75 if (( pwd = uam_getname(obj, username, ulen)) == NULL ) { 76 return AFPERR_NOTAUTH; 77 } 78 79 LOG(log_info, logtype_uams, "cleartext login: %s", username); 80 81 if (uam_checkuser(pwd) < 0) { 82 LOG(log_info, logtype_uams, "not a valid user"); 83 return AFPERR_NOTAUTH; 84 } 85 86#ifdef SHADOWPW 87 if (( sp = getspnam( pwd->pw_name )) == NULL ) { 88 LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username); 89 return AFPERR_NOTAUTH; 90 } 91 pwd->pw_passwd = sp->sp_pwdp; 92 93 if (sp->sp_max != -1 && sp->sp_lstchg) { 94 time_t now = time(NULL) / (60*60*24); 95 int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; 96 if ( expire_days < 0 ) { 97 LOG(log_info, logtype_uams, "Password for user %s expired", username); 98 err = AFPERR_PWDEXPR; 99 } 100 } 101#endif /* SHADOWPW */ 102 103 if (!pwd->pw_passwd) { 104 return AFPERR_NOTAUTH; 105 } 106 107 *uam_pwd = pwd; 108 109#ifdef TRU64 110 { 111 int ac; 112 char **av; 113 char hostname[256]; 114 115 uam_afp_getcmdline( &ac, &av ); 116 sprintf( hostname, "%s@%s", username, clientname ); 117 118 if( uam_sia_validate_user( NULL, ac, av, hostname, username, 119 NULL, FALSE, NULL, ibuf ) != SIASUCCESS ) 120 return AFPERR_NOTAUTH; 121 122 return err; 123 } 124#else /* TRU64 */ 125 p = crypt( ibuf, pwd->pw_passwd ); 126 if ( strcmp( p, pwd->pw_passwd ) == 0 ) 127 return err; 128#endif /* TRU64 */ 129 130 return AFPERR_NOTAUTH; 131 132} 133 134/* cleartxt login */ 135static int passwd_login(void *obj, struct passwd **uam_pwd, 136 char *ibuf, size_t ibuflen, 137 char *rbuf, size_t *rbuflen) 138{ 139 char *username; 140 size_t len, ulen; 141 142 *rbuflen = 0; 143 144 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, 145 (void *) &username, &ulen) < 0) 146 return AFPERR_MISC; 147 148 if (ibuflen < 2) { 149 return( AFPERR_PARAM ); 150 } 151 152 len = (unsigned char) *ibuf++; 153 ibuflen--; 154 if (!len || len > ibuflen || len > ulen ) { 155 return( AFPERR_PARAM ); 156 } 157 memcpy(username, ibuf, len ); 158 ibuf += len; 159 ibuflen -=len; 160 username[ len ] = '\0'; 161 162 if ((unsigned long) ibuf & 1) { /* pad character */ 163 ++ibuf; 164 ibuflen--; 165 } 166 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); 167 168} 169 170/* cleartxt login ext 171 * uname format : 172 byte 3 173 2 bytes len (network order) 174 len bytes unicode name 175*/ 176static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd, 177 char *ibuf, size_t ibuflen, 178 char *rbuf, size_t *rbuflen) 179{ 180 char *username; 181 size_t len, ulen; 182 uint16_t temp16; 183 184 *rbuflen = 0; 185 186 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, 187 (void *) &username, &ulen) < 0) 188 return AFPERR_MISC; 189 190 if (*uname != 3) 191 return AFPERR_PARAM; 192 uname++; 193 memcpy(&temp16, uname, sizeof(temp16)); 194 len = ntohs(temp16); 195 if (!len || len > ulen ) { 196 return( AFPERR_PARAM ); 197 } 198 memcpy(username, uname +2, len ); 199 username[ len ] = '\0'; 200 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen)); 201} 202 203 204#if 0 205/* change passwd */ 206static int passwd_changepw(void *obj, char *username, 207 struct passwd *pwd, char *ibuf, 208 size_t ibuflen, char *rbuf, size_t *rbuflen) 209{ 210#ifdef SHADOWPW 211 struct spwd *sp; 212#endif /* SHADOWPW */ 213 char pw[PASSWDLEN + 1], *p; 214 uid_t uid = geteuid(); 215 216 if (uam_checkuser(pwd) < 0) 217 return AFPERR_ACCESS; 218 219 /* old password */ 220 memcpy(pw, ibuf, PASSWDLEN); 221 memset(ibuf, 0, PASSWDLEN); 222 pw[PASSWDLEN] = '\0'; 223 224#ifdef SHADOWPW 225 if (( sp = getspnam( pwd->pw_name )) == NULL ) { 226 LOG(log_info, logtype_uams, "no shadow passwd entry for %s", username); 227 return AFPERR_PARAM; 228 } 229 pwd->pw_passwd = sp->sp_pwdp; 230#endif /* SHADOWPW */ 231 232 p = crypt(pw, pwd->pw_passwd ); 233 if (strcmp( p, pwd->pw_passwd )) { 234 memset(pw, 0, sizeof(pw)); 235 return AFPERR_NOTAUTH; 236 } 237 238 /* new password */ 239 ibuf += PASSWDLEN; 240 ibuf[PASSWDLEN] = '\0'; 241 242#ifdef SHADOWPW 243#else /* SHADOWPW */ 244#endif /* SHADOWPW */ 245 return AFP_OK; 246} 247#endif /* 0 */ 248 249 250/* Printer ClearTxtUAM login */ 251static int passwd_printer(char *start, char *stop, char *username, struct papfile *out) 252{ 253 struct passwd *pwd; 254#ifdef SHADOWPW 255 struct spwd *sp; 256#endif /* SHADOWPW */ 257 char *data, *p, *q; 258 char password[PASSWDLEN + 1] = "\0"; 259 static const char *loginok = "0\r"; 260 int ulen; 261 262 data = (char *)malloc(stop - start + 1); 263 if (!data) { 264 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: malloc"); 265 return(-1); 266 } 267 strlcpy(data, start, stop - start + 1); 268 269 /* We are looking for the following format in data: 270 * (username) (password) 271 * 272 * Let's hope username doesn't contain ") ("! 273 */ 274 275 /* Parse input for username in () */ 276 if ((p = strchr(data, '(' )) == NULL) { 277 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); 278 free(data); 279 return(-1); 280 } 281 p++; 282 if ((q = strstr(p, ") (" )) == NULL) { 283 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: username not found in string"); 284 free(data); 285 return(-1); 286 } 287 memcpy(username, p, MIN( UAM_USERNAMELEN, q - p )); 288 289 /* Parse input for password in next () */ 290 p = q + 3; 291 if ((q = strrchr(p , ')' )) == NULL) { 292 LOG(log_info, logtype_uams,"Bad Login ClearTxtUAM: password not found in string"); 293 free(data); 294 return(-1); 295 } 296 memcpy(password, p, MIN(PASSWDLEN, q - p) ); 297 298 /* Done copying username and password, clean up */ 299 free(data); 300 301 ulen = strlen(username); 302 303 if (( pwd = uam_getname(NULL, username, ulen)) == NULL ) { 304 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: ( %s ) not found ", 305 username); 306 return(-1); 307 } 308 309 if (uam_checkuser(pwd) < 0) { 310 /* syslog of error happens in uam_checkuser */ 311 return(-1); 312 } 313 314#ifdef SHADOWPW 315 if (( sp = getspnam( pwd->pw_name )) == NULL ) { 316 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no shadow passwd entry for %s", 317 username); 318 return(-1); 319 } 320 pwd->pw_passwd = sp->sp_pwdp; 321 322 if (sp->sp_max != -1 && sp->sp_lstchg) { 323 time_t now = time(NULL) / (60*60*24); 324 int32_t expire_days = sp->sp_lstchg - now + sp->sp_max; 325 if ( expire_days < 0 ) { 326 LOG(log_info, logtype_uams, "Password for user %s expired", username); 327 return (-1); 328 } 329 } 330 331#endif /* SHADOWPW */ 332 333 if (!pwd->pw_passwd) { 334 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: no password for %s", 335 username); 336 return(-1); 337 } 338 339#ifdef AFS 340 if ( kcheckuser( pwd, password) == 0) 341 return(0); 342#endif /* AFS */ 343 344 p = crypt(password, pwd->pw_passwd); 345 if (strcmp(p, pwd->pw_passwd) != 0) { 346 LOG(log_info, logtype_uams, "Bad Login ClearTxtUAM: %s: bad password", username); 347 return(-1); 348 } 349 350 /* Login successful */ 351 append(out, loginok, strlen(loginok)); 352 LOG(log_info, logtype_uams, "Login ClearTxtUAM: %s", username); 353 return(0); 354} 355 356static int uam_setup(const char *path) 357{ 358 if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Cleartxt Passwrd", 359 passwd_login, NULL, NULL, passwd_login_ext) < 0) 360 return -1; 361 if (uam_register(UAM_SERVER_PRINTAUTH, path, "ClearTxtUAM", 362 passwd_printer) < 0) 363 return -1; 364 365 return 0; 366} 367 368static void uam_cleanup(void) 369{ 370 uam_unregister(UAM_SERVER_LOGIN, "Cleartxt Passwrd"); 371 uam_unregister(UAM_SERVER_PRINTAUTH, "ClearTxtUAM"); 372} 373 374UAM_MODULE_EXPORT struct uam_export uams_clrtxt = { 375 UAM_MODULE_SERVER, 376 UAM_MODULE_VERSION, 377 uam_setup, uam_cleanup 378 }; 379 380UAM_MODULE_EXPORT struct uam_export uams_passwd = { 381 UAM_MODULE_SERVER, 382 UAM_MODULE_VERSION, 383 uam_setup, uam_cleanup 384 }; 385