Pdb_mysql

Jelmer Vernooij jelmer at nl.linux.org
Thu Feb 22 19:25:15 GMT 2001


Sorry, I forgot the file :(

Here's mysql.c
	
Jelmer

-- 
Jelmer Vernooij <jelmer at nl.linux.org> - http://nl.linux.org/~jelmer/
Playing MPEG stream from The Offspring - Amazed.mp3 ...
Host: charis.vernstok, an i686 running Linux 2.2.12-20
  8:24pm  up  4:32,  6 users,  load average: 0.47, 0.22, 0.18
-------------- next part --------------
/*
 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
 * MySQL module and changes (c) 2000-2001 Jelmer Vernooij <jelmer at nl.linux.org>
 * 
 * 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.
 */

/* TODO:
   Support for adding users
   Support for deleting users
   Clean up the code
 */

#ifdef WITH_MYSQL

#include "includes.h"

#include <mysql/mysql.h>

extern int DEBUGLEVEL;
extern pstring samlogon_user;
extern BOOL sam_logon_in_ssb;

MYSQL *pdb_mysql_connect();
MYSQL_RES *global_res = NULL;

static void mysqlerr(MYSQL *a){
    char *tmp = malloc(21 + strlen(mysql_error(a)) + strlen(": \n"));
    DEBUG(0, ("pdb_mysql: Error occured while executing SQL query!\n"));
    DEBUG(0,("pdb_mysql: %d: %s\n", mysql_errno(a), mysql_error(a)));
}

/***************************************************************
  Start to enumerate the smbpasswd list. Returns a void pointer
  to ensure no modification outside this module.
 ****************************************************************/

BOOL pdb_setsampwent(BOOL update)
{
    MYSQL *mysql_auth;
    mysql_auth = pdb_mysql_connect();
    if(mysql_query(mysql_auth, "SELECT * FROM leerling") != 0)
	mysqlerr(mysql_auth);
    global_res = mysql_store_result(mysql_auth);
    if(!global_res){
	mysqlerr(mysql_auth);
	return FALSE;
    }
    mysql_close(mysql_auth);
    return TRUE;
}

/***************************************************************
  End enumeration of the smbpasswd list - operate on the default
  lock_depth.
 ****************************************************************/

void endmysqlpwent(void)
{
    if(global_res != NULL)mysql_free_result((MYSQL_RES *)global_res);
    global_res = NULL;
}

/*************************************************************************
  Routine to return the next entry in the smbpasswd list.
 *************************************************************************/

SAM_ACCOUNT *mysql_getrow(char *n, MYSQL_RES *vp){
    /* Static buffers we will return. */
    static SAM_ACCOUNT pw_buf;
    static char smbpwd[64];
    static char smbntpwd[64];
    static pstring full_name;
    static pstring home_dir;
    static pstring home_drive;
    static pstring logon_script;
    static pstring profile_path;
    static pstring acct_desc;
    MYSQL_ROW row;
    MYSQL *mysql_auth = pdb_mysql_connect();
    char *tmp;
    MYSQL_RES *result = vp;
    pdb_init_sam(&pw_buf);
    pw_buf.acct_ctrl = ACB_NORMAL;  
    /*
     * Scan the file, a line at a time and check if the name matches.
     */
    if(vp == NULL){
	char *bla = malloc(strlen(n) * 2 + 1);
	MYSQL *mysql_auth = pdb_mysql_connect();
	mysql_escape_string(bla, n, strlen(n));
	asprintf(tmp, "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE ID = '%s' || nick = '%s'\n", 
		lp_mysql_colusername(), 
		lp_mysql_coluid(), 
		lp_mysql_colacct(), 
		lp_mysql_collanman(),
		lp_mysql_colntpwd(),
		lp_mysql_colplain(),
		lp_mysql_pwd_set(), 
    		lp_mysql_colfname(),
		lp_mysql_colhome(),
		lp_mysql_coldrive(),
		lp_mysql_colscript(),
		lp_mysql_colprofile(),
    		lp_mysql_coldesc(),
    		lp_mysql_colgroup(),
		n[strlen(n)-1] == '$'?lp_mysql_tabmach():lp_mysql_tabuser(), bla, bla);
	mysql_query(mysql_auth, tmp);
	result = mysql_store_result(mysql_auth);
	mysql_close(mysql_auth);
    }
    if((row = mysql_fetch_row(result)) != NULL) {
	if(row[0] != NULL)pw_buf.username = row[0]; /* Check if username is present */
	else pw_buf.username = strdup(row[1]);
	pw_buf.uid = atol(row[1]);
	/*
	 * 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.
	 */
	if(row[2] == NULL)pw_buf.acct_ctrl = 0;
	else pw_buf.acct_ctrl = pdb_decode_acct_ctrl(row[2]);
	/* Must have some account type set. */
	if(pw_buf.acct_ctrl == 0)
	    pw_buf.acct_ctrl = ACB_NORMAL;

	if(!lp_mysql_plain()){
	    if (row[3] != NULL && (*row[3] == '*' || *row[3] == 'X')) {
		/* Password deliberately invalid - end here. */
		DEBUG(0, ("getmysqlpwent: entry invalidated for user %s\n", pw_buf.username));
		pw_buf.nt_pw = NULL;
		pw_buf.lm_pw = NULL;
		pw_buf.acct_ctrl |= ACB_DISABLED;
		return &pw_buf;
	    }

	    if (row[3] == NULL || !strncasecmp((char *) row[3], "NULL", 4) || !strncasecmp((char *) row[3], "NO PASSWORD", 11)) {
		pw_buf.lm_pw = NULL;
		pw_buf.acct_ctrl |= ACB_PWNOTREQ;
	    } else {
		if (!pdb_gethexpwd((char *)row[3], smbpwd)) {
		    DEBUG(0, ("getmysqlpwent: Malformed Lanman password entry (non hex chars)\n"));
		    return &pw_buf;
		}
		pw_buf.lm_pw = smbpwd;
	    }

	    /* 
	     * Now check if the NT compatible password is
	     * available.
	     */
	    pw_buf.nt_pw = NULL;

	    if (row[4] != NULL && *row[4] != '*' && *row[4] != 'X' && strcmp(row[4], "NULL")) {
		if(pdb_gethexpwd((char *)row[4],smbntpwd))
		    pw_buf.nt_pw = smbntpwd;
	    }else pw_buf.acct_ctrl |= ACB_PWNOTREQ;
	}else {
	    nt_lm_owf_gen(row[5], pw_buf.nt_pw, pw_buf.lm_pw);
	}
	if(row[6] == NULL)pw_buf.pass_last_set_time = 0;
	else pw_buf.pass_last_set_time = atol(row[6]);
	pstrcpy(full_name, row[7] == NULL?"":row[7]);
	pw_buf.full_name = full_name;
	
	pstrcpy(home_dir, row[8] == NULL?lp_logon_home():row[8]);
	pw_buf.home_dir = home_dir;

	pstrcpy(home_drive, row[9] == NULL?lp_logon_drive():row[9]);
	pw_buf.dir_drive = home_drive;

	pstrcpy(logon_script, row[10] == NULL?lp_logon_script():row[10]);
	pw_buf.logon_script = logon_script;

	pstrcpy(profile_path, row[11] == NULL?lp_logon_path():row[11]);
	pw_buf.profile_path = profile_path;

	pw_buf.acct_desc = row[12];
	pw_buf.gid = (row[13] == NULL?99:atol(row[13])); /* Hmm.. not a very good solution, using group 99, 'nobody'? */
	if(pw_buf.username[strlen(pw_buf.username)-1] == '$')
	    pw_buf.gid = DOMAIN_GROUP_RID_USERS;
	pw_buf.user_rid  = pdb_uid_to_user_rid (pw_buf.uid);
	pw_buf.group_rid = pdb_gid_to_group_rid(pw_buf.gid);
	
	return &pw_buf;
    }
    if(vp == NULL)mysql_free_result(result); 
    DEBUG(5,("getmysqlpwent: end of file reached.\n"));
    return NULL;
}

SAM_ACCOUNT *pdb_getsampwent(void)
{
    return mysql_getrow(NULL, global_res);
}

SAM_ACCOUNT *pdb_getsampwnam(char *n){
    return mysql_getrow(n, NULL);
}

/************************************************************************
  Routine to add an entry to the smbpasswd file.
 *************************************************************************/

BOOL pdb_add_sam_account(SAM_ACCOUNT *newpwd)
{
    DEBUG(0, ("FIXME: Someone was trying to add a user!\n"));
    return False;
}

/************************************************************************
  Routine to search the smbpasswd file for an entry matching the username.
  and then modify its password entry. We can't use the startsmbpwent()/
  getsmbpwent()/endsmbpwent() interfaces here as we depend on looking
  in the actual file to decide how much room we have to write data.
  override = False, normal
  override = True, override XXXXXXXX'd out password or NO PASS
 ************************************************************************/

BOOL pdb_update_sam_account(SAM_ACCOUNT* pwd, BOOL override)
{
    /* Static buffers we will return. */

    char            *linebuf;
    fstring         ascii_p16;
    fstring	  ascii_p32;
    char		  escAscii_p16[64], escAscii_p32[64];
    fstring         encode_bits;
    MYSQL *mysql_auth = pdb_mysql_connect();

    int i;
    int wr_len;

    /*
     * If both NT and lanman passwords are provided - reset password
     * not required flag.
     */

    if(pwd->lm_pw != NULL || pwd->nt_pw != NULL) {
	/* Reqiure password in the future (should ACB_DISABLED also be reset?) */
	pwd->acct_ctrl &= ~(ACB_PWNOTREQ);
    }

    /* ?????
     * We are using a new format, space padded
     * acct ctrl field. Encode the given acct ctrl
     * bits into it.
     */
    fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));


    /* Create the 32 byte representation of the new p16 */
    if(pwd->lm_pw != NULL) {
	for (i = 0; i < 16; i++) {
	    slprintf(&ascii_p16[i*2], sizeof(fstring) - 1, "%02X", (uchar) pwd->lm_pw[i]);
	}
    } else {
	if(pwd->acct_ctrl & ACB_PWNOTREQ)
	    fstrcpy(ascii_p16, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
	else
	    fstrcpy(ascii_p16, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    }
    mysql_escape_string(escAscii_p16, ascii_p16, 32);
    /* Add on the NT md4 hash */
    wr_len = 66;
    if (pwd->nt_pw != NULL) {
	for (i = 0; i < 16; i++) {
	    slprintf(&ascii_p32[(i*2)], sizeof(fstring) - 1, "%02X", (uchar) pwd->nt_pw[i]);
	}
    } else {
	if(pwd->acct_ctrl & ACB_PWNOTREQ)
	    fstrcpy(&ascii_p32[0], "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
	else
	    fstrcpy(&ascii_p32[0], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    }
    mysql_escape_string(escAscii_p32, ascii_p32, 32);

    /* Add on the account info bits and the time of last
       password change. */

    pwd->pass_last_set_time = time(NULL);

    asprintf(linebuf, "UPDATE %s SET uaccountctrl = '%s', unicode_ww = '%s', dbcspwd = '%s', pwd_last_set = '%ld' WHERE ID = '%s' || nick = '%s'\n", 
	    pwd->username[strlen(pwd->username)-1] ==
	    '$'?lp_mysql_tabmach():lp_mysql_tabuser(),encode_bits, escAscii_p16, escAscii_p32, time(NULL), pwd->username, pwd->username);
    mysql_query(mysql_auth, linebuf);
    mysql_close(mysql_auth);
    return True;
}

/************************************************************************
  Routine to delete an entry in the smbpasswd file by name.
 *************************************************************************/

BOOL pdb_delete_sam_account(char *name)
{
    DEBUG(0, ("FIXME:Someone was trying to delete a user\n"));
    return True;
}

MYSQL *pdb_mysql_connect(){
    MYSQL *auth_sql_server = malloc(sizeof(MYSQL));
    MYSQL_RES *res;
    char tmp[100];
    mysql_init (auth_sql_server);
    if(!mysql_real_connect (auth_sql_server,lp_mysql_host(),lp_mysql_user(),
		lp_mysql_pass(),lp_mysql_db(), 0, NULL, 0)){
	DEBUG(0, ("pdb_mysql: Error while connecting to database!\n"));
	mysqlerr(auth_sql_server);
    }
    if (mysql_select_db (auth_sql_server, lp_mysql_db()) != 0) {
	DEBUG(0, ("pdb_mysql: Error while selecting database!\n"));
	mysqlerr(auth_sql_server);
    }
    DEBUG(1,("Connected to database: "));
    DEBUG(1,(mysql_get_host_info(auth_sql_server)));DEBUG(1,(","));
    DEBUG(1,(mysql_get_server_info(auth_sql_server)));DEBUG(1,("\n"));
    return auth_sql_server;
}

#else 
void pdb_mysql_dummy_function(){} /* Dummy function to stop compilers from complaining */
#endif


More information about the samba-technical mailing list