This is smbpass.c in view mode; [Download] [Up]
#ifdef SMB_PASSWD /* * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup * Copyright (C) Andrew Tridgell 1992-1997 Modified by Jeremy Allison 1995. * * 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 2 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., 675 * Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" extern int DEBUGLEVEL; int gotalarm; void gotalarm_sig() { gotalarm = 1; } int do_pw_lock(int fd, int waitsecs, int type) { int ret; #ifndef BSD_LOCK struct flock lock; lock.l_type = type; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 1; lock.l_pid = 0; #endif gotalarm = 0; signal(SIGALRM, SIGNAL_CAST gotalarm_sig); alarm(5); #ifdef BSD_LOCK ret = flock(fd, (type==F_UNLCK)?LOCK_UN:LOCK_EX); #else ret = fcntl(fd, F_SETLKW, &lock); #endif alarm(0); signal(SIGALRM, SIGNAL_CAST SIG_DFL); if (gotalarm) { DEBUG(0, ("do_pw_lock: failed to %s SMB passwd file.\n", type == F_UNLCK ? "unlock" : "lock")); return -1; } return ret; } int pw_file_lock(char *name, int type, int secs) { int fd = open(name, O_RDWR | O_CREAT, 0600); if (fd < 0) return (-1); if (do_pw_lock(fd, secs, type)) { close(fd); return -1; } return fd; } int pw_file_unlock(int fd) { do_pw_lock(fd, 5, F_UNLCK); return close(fd); } /* * Routine to get the next 32 hex characters and turn them * into a 16 byte array. */ static int gethexpwd(char *p, char *pwd) { int i; unsigned char lonybble, hinybble; char *hexchars = "0123456789ABCDEF"; char *p1, *p2; for (i = 0; i < 32; i += 2) { hinybble = toupper(p[i]); lonybble = toupper(p[i + 1]); p1 = strchr(hexchars, hinybble); p2 = strchr(hexchars, lonybble); if (!p1 || !p2) return (False); hinybble = PTR_DIFF(p1, hexchars); lonybble = PTR_DIFF(p2, hexchars); pwd[i / 2] = (hinybble << 4) | lonybble; } return (True); } #ifdef USE_NETINFO /* * The code to use when accesssing netinfo on NEXTSTEP/OPENSTEP */ #include "netinfo/ni_crypt.c" struct smb_passwd *get_smbpwnam_from_file(char *name); struct smb_passwd *get_smbpwnam(char *name) { /* Static buffers we will return. */ static struct smb_passwd pw_buf; static pstring user_name; static unsigned char smbpwd[16]; static unsigned char smbntpwd[16]; char *pfile = lp_smb_passwd_file(); ni_status status; ni_namelist passwd, ntpasswd; ni_id ndir; void *handle; char *ldir; DEBUG(10, ("get_smbpwnam: opening netinfo for samba passwords for user %s.\n", name)); /* Set the directory to get. */ ldir = (char *)malloc(sizeof(char)*(8+strlen(name))); (void)strcpy(ldir, S_USERDIR); (void)strcat(ldir, "/"); (void)strcat(ldir, name); /* * Scan the NetInfo hierarchy, starting from the local level, * until either an entry is found or we are past the top level. */ handle = NULL; status = ni_search_for_dir(ldir, ".", &handle, &ndir, 5, 0, 1); free(ldir); if (status == NI_OK) { /* Do we have a samba password? */ status = ni_lookupprop(handle, &ndir, S_SMBPASSWD, &passwd); if ((status == NI_OK) && (passwd.ni_namelist_len)) { /* If the password starts with 'X' or '*', the entry has been disabled. */ if ((*(passwd.ni_namelist_val[0]) == '*') || (*(passwd.ni_namelist_val[0]) == 'X')) { DEBUG(10, ("get_smbpwnam: entry invalidated for user %s\n", name)); ni_namelist_free(&passwd); ni_free(handle); return NULL; } if (!strncasecmp(passwd.ni_namelist_val[0], "NO PASSWORD", 11)) { pw_buf.smb_passwd = NULL; } else { ni_decrypt(passwd.ni_namelist_val[0], (char *)smbpwd); pw_buf.smb_passwd = smbpwd; } ni_namelist_free(&passwd); /* User name must be identical to name passed. */ strcpy(user_name, name); pw_buf.smb_name = user_name; /* Get uid. */ status = ni_lookupprop(handle, &ndir, "uid", &passwd); if ((status == NI_OK) && (passwd.ni_namelist_len)) { pw_buf.smb_userid = atoi(passwd.ni_namelist_val[0]); ni_namelist_free(&passwd); } else { if (status == NI_OK) ni_namelist_free(&passwd); DEBUG(0, ("get_smbpwnam: could not read uid from NetInfo\n")); ni_free(handle); return NULL; } pw_buf.smb_nt_passwd = NULL; /* Do we have an NT password? */ status = ni_lookupprop(handle, &ndir, S_SMBNTPASSWD, &ntpasswd); if (status == NI_OK) { if (ntpasswd.ni_namelist_len) { if (*(ntpasswd.ni_namelist_val[0]) != '*' && *(ntpasswd.ni_namelist_val[0]) != 'X') { ni_decrypt(ntpasswd.ni_namelist_val[0], (char *)smbntpwd); pw_buf.smb_nt_passwd = smbntpwd; } } ni_namelist_free(&ntpasswd); } DEBUG(5, ("get_smbpwname: returning passwd entry for user %s, uid %d\n", user_name, pw_buf.smb_userid)); ni_free(handle); return &pw_buf; } else if (status == NI_OK) ni_namelist_free(&passwd); } DEBUG(0, ("get_smbpwnam: could not find %s in any NetInfo domain\n", ldir)); if (pfile && *pfile && strcmp("netinfo", pfile)) { DEBUG(0, ("get_smbpwnam: trying flat file %s\n", ldir)); return get_smbpwnam_from_file(name); } return NULL; } #define get_smbpwnam get_smbpwnam_from_file #endif /* USE_NETINFO */ /* * Routine to search the smbpasswd file for an entry matching the username. */ struct smb_passwd *get_smbpwnam(char *name) { /* Static buffers we will return. */ static struct smb_passwd pw_buf; static pstring user_name; static unsigned char smbpwd[16]; static unsigned char smbntpwd[16]; char linebuf[256]; char readbuf[16 * 1024]; unsigned char c; unsigned char *p; long uidval; long linebuf_len; FILE *fp; int lockfd; char *pfile = lp_smb_passwd_file(); if (!*pfile) { DEBUG(0, ("No SMB password file set\n")); return (NULL); } DEBUG(10, ("get_smbpwnam: opening file %s\n", pfile)); fp = fopen(pfile, "r"); if (fp == NULL) { DEBUG(0, ("get_smbpwnam: unable to open file %s\n", pfile)); return NULL; } /* Set a 16k buffer to do more efficient reads */ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); if ((lockfd = pw_file_lock(pfile, F_RDLCK, 5)) < 0) { DEBUG(0, ("get_smbpwnam: unable to lock file %s\n", pfile)); fclose(fp); return NULL; } /* make sure it is only rw by the owner */ chmod(pfile, 0600); /* We have a read lock on the file. */ /* * Scan the file, a line at a time and check if the name matches. */ while (!feof(fp)) { linebuf[0] = '\0'; fgets(linebuf, 256, fp); if (ferror(fp)) { fclose(fp); pw_file_unlock(lockfd); return NULL; } /* * Check if the string is terminated with a newline - if not * then we must keep reading and discard until we get one. */ linebuf_len = strlen(linebuf); if (linebuf[linebuf_len - 1] != '\n') { c = '\0'; while (!ferror(fp) && !feof(fp)) { c = fgetc(fp); if (c == '\n') break; } } else linebuf[linebuf_len - 1] = '\0'; #ifdef DEBUG_PASSWORD DEBUG(100, ("get_smbpwnam: got line |%s|\n", linebuf)); #endif if ((linebuf[0] == 0) && feof(fp)) { DEBUG(4, ("get_smbpwnam: end of file reached\n")); break; } /* * The line we have should be of the form :- * * username:uid:[32hex bytes]:....other flags presently * ignored.... * * or, * * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... * * if Windows NT compatible passwords are also present. */ if (linebuf[0] == '#' || linebuf[0] == '\0') { DEBUG(6, ("get_smbpwnam: skipping comment or blank line\n")); continue; } p = (unsigned char *) strchr(linebuf, ':'); if (p == NULL) { DEBUG(0, ("get_smbpwnam: malformed password entry (no :)\n")); continue; } /* * As 256 is shorter than a pstring we don't need to check * length here - if this ever changes.... */ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); user_name[PTR_DIFF(p, linebuf)] = '\0'; if (!strequal(user_name, name)) continue; /* User name matches - get uid and password */ p++; /* Go past ':' */ if (!isdigit(*p)) { DEBUG(0, ("get_smbpwnam: malformed password entry (uid not number)\n")); fclose(fp); pw_file_unlock(lockfd); return NULL; } uidval = atoi((char *) p); while (*p && isdigit(*p)) p++; if (*p != ':') { DEBUG(0, ("get_smbpwnam: malformed password entry (no : after uid)\n")); fclose(fp); pw_file_unlock(lockfd); return NULL; } /* * Now get the password value - this should be 32 hex digits * which are the ascii representations of a 16 byte string. * Get two at a time and put them into the password. */ p++; if (*p == '*' || *p == 'X') { /* Password deliberately invalid - end here. */ DEBUG(10, ("get_smbpwnam: entry invalidated for user %s\n", user_name)); fclose(fp); pw_file_unlock(lockfd); return NULL; } if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("get_smbpwnam: malformed password entry (passwd too short)\n")); fclose(fp); pw_file_unlock(lockfd); return (False); } if (p[32] != ':') { DEBUG(0, ("get_smbpwnam: malformed password entry (no terminating :)\n")); fclose(fp); pw_file_unlock(lockfd); return NULL; } if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { pw_buf.smb_passwd = NULL; } else { if(!gethexpwd((char *)p,(char *)smbpwd)) { DEBUG(0, ("Malformed Lanman password entry (non hex chars)\n")); fclose(fp); pw_file_unlock(lockfd); return NULL; } pw_buf.smb_passwd = smbpwd; } pw_buf.smb_name = user_name; pw_buf.smb_userid = uidval; pw_buf.smb_nt_passwd = NULL; /* Now check if the NT compatible password is available. */ p += 33; /* Move to the first character of the line after the lanman password. */ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { if (*p != '*' && *p != 'X') { if(gethexpwd((char *)p,(char *)smbntpwd)) pw_buf.smb_nt_passwd = smbntpwd; } } fclose(fp); pw_file_unlock(lockfd); DEBUG(5, ("get_smbpwname: returning passwd entry for user %s, uid %d\n", user_name, uidval)); return &pw_buf; } fclose(fp); pw_file_unlock(lockfd); return NULL; } #else void smbpass_dummy(void) { } /* To avoid compiler complaints */ #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.