mirror of
https://github.com/samba-team/samba.git
synced 2025-11-06 08:23:50 +03:00
1) put the encryption code in by default, with no #ifdef. It is still disabled by default so you need to add "encrypt passwords = yes" in smb.conf but at least all binaries will have it. 2) cleanup the kanji code so it compiles with no warnings 3) get rid of lots of uses of ugly non-portable C code. The main offender being things like "register" but also remove uses of the "const" keyword as there are compilers out there that don't support it and even those that do often complain about its usage. Users don't like warnings :-( There is still some work to do. We need to replace the md4 code with our own implementation. The current code (from rfc1186) is PD but is not very portable. The new RFC (rfc1320) is more portable but adds copyright restrictions. I'll do a from-scratch MD4 soon. We also need to test that what I've implemented is portable. It should be, but I'm too tired right now to test it on anything other than intel linux.
-
294 lines
7.2 KiB
C
294 lines
7.2 KiB
C
/*
|
|
* 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)
|
|
{
|
|
struct flock lock;
|
|
int ret;
|
|
|
|
gotalarm = 0;
|
|
signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
|
|
|
|
lock.l_type = type;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = 0;
|
|
lock.l_len = 1;
|
|
lock.l_pid = 0;
|
|
|
|
alarm(5);
|
|
ret = fcntl(fd, F_SETLKW, &lock);
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|