From ec934124db8a5234d8c83799a23c7bdced5dd95a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Aug 2005 22:01:18 +0000 Subject: [PATCH] r9762: Add support for reading good old smbpasswd files Fix password support Make base64 decode/encode functions available to EJS (This used to be commit 1376a1fe44cd6b01709819095a711c14626b1d3e) --- source4/lib/samba3/samba3.h | 4 +- source4/lib/samba3/smbpasswd.c | 132 ++++++++++++++++++++++++ source4/lib/samba3/tdbsam.c | 32 +++--- source4/scripting/ejs/smbcalls_ldb.c | 61 +++++++++++ source4/scripting/ejs/smbcalls_samba3.c | 4 +- source4/scripting/libjs/upgrade.js | 59 ++++++----- 6 files changed, 250 insertions(+), 42 deletions(-) diff --git a/source4/lib/samba3/samba3.h b/source4/lib/samba3/samba3.h index 5aba790c4ea..a41109a145e 100644 --- a/source4/lib/samba3/samba3.h +++ b/source4/lib/samba3/samba3.h @@ -22,6 +22,7 @@ #define _SAMBA3_H #include "librpc/gen_ndr/security.h" +#include "librpc/gen_ndr/samr.h" struct samba3_samaccount { uint32_t logon_time, @@ -43,10 +44,11 @@ struct samba3_samaccount { char *profile_path; char *acct_desc; char *workstations; + uid_t uid; uint32_t user_rid, group_rid, hours_len, unknown_6; uint16_t acct_ctrl, logon_divs; uint16_t bad_password_count, logon_count; - uint8_t *lm_pw_ptr, *nt_pw_ptr; + struct samr_Password lm_pw, nt_pw; uint8_t *nt_pw_hist_ptr; uint8_t *hours; }; diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index bcbb5e56d89..5976d2db572 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -7,6 +7,7 @@ Modified by Gerald (Jerry) Carter 2000-2001 Copyright (C) Tim Potter 2001 Copyright (C) Andrew Bartlett 2005 + Copyright (C) Jelmer Vernooij 2005 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 @@ -54,6 +55,7 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_samr.h" +#include "lib/samba3/samba3.h" #include "system/iconv.h" /*! Convert 32 hex characters into a 16 byte array. */ @@ -206,3 +208,133 @@ char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info) return acct_str; } + +NTSTATUS samba3_read_smbpasswd(const char *filename, TALLOC_CTX *ctx, struct samba3_samaccount **accounts, uint32_t *count) +{ + int numlines; + char **lines; + *count = 0; + *accounts = NULL; + int i; + + lines = file_lines_load(filename, &numlines, ctx); + + *accounts = talloc_array(ctx, struct samba3_samaccount, numlines); + + for (i = 0; i < numlines; i++) { + char *p = lines[i], *q; + struct samba3_samaccount *acc = &((*accounts)[*count]); + + if (p[0] == '\0' || p[0] == '#') + continue; + + ZERO_STRUCTP(acc); + + q = strchr(p, ':'); + if (!q) { + DEBUG(0, ("%s:%d: expected ':'\n", filename, i)); + continue; + } + + acc->username = talloc_strndup(ctx, p, PTR_DIFF(q, p)); + p = q+1; + + acc->uid = atoi(p); + + q = strchr(p, ':'); + if (!q) { + DEBUG(0, ("%s:%d: expected ':'\n", filename, i)); + continue; + } + p = q+1; + + if (strlen(p) < 33) { + DEBUG(0, ("%s:%d: expected 32 byte password blob\n", filename, i)); + continue; + } + + if (!strncmp(p, "NO PASSWORD", strlen("NO PASSWORD"))) { + acc->acct_ctrl |= ACB_PWNOTREQ; + } else if (p[0] == '*' || p[0] == 'X') { + /* No password set */ + } else { + struct samr_Password *pw = smbpasswd_gethexpwd(*accounts, p); + + if (!pw) { + DEBUG(0, ("%s:%d: Malformed LM pw entry\n", filename, i)); + continue; + } + + memcpy(acc->lm_pw.hash, pw, sizeof(*pw)); + } + + if (p[32] != ':') { + DEBUG(0, ("%s:%d: expected ':' after 32 byte password blob\n", filename, i)); + continue; + } + + p += 33; + + if (p[0] == '*' || p[0] == 'X') { + /* No password set */ + } else { + struct samr_Password *pw = smbpasswd_gethexpwd(*accounts, p); + + if (!pw) { + DEBUG(0, ("%s:%d: Malformed LM pw entry\n", filename, i)); + continue; + } + + memcpy(acc->nt_pw.hash, pw, sizeof(*pw)); + } + + if (p[32] != ':') { + DEBUG(0, ("%s:%d: expected ':' after 32 byte password blob\n", filename, i)); + continue; + } + + p += 33; + + if (p[0] == '[') { + q = strchr(p, ']'); + if (!q) { + DEBUG(0, ("%s:%d: expected ']'\n", filename, i)); + continue; + } + + acc->acct_ctrl |= smbpasswd_decode_acb_info(p); + + p = q+1; + if (p[0] == ':' && strncmp(p, "LCT-", 4) == 0) { + int j; + p += 4; + + for(j = 0; j < 8; j++) { + if(p[j] == '\0' || !isxdigit(p[j])) { + break; + } + } + if(i == 8) { + acc->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16); + } + } + } else { + /* 'Old' style file. Fake up based on user name. */ + /* + * Currently trust accounts are kept in the same + * password file as 'normal accounts'. If this changes + * we will have to fix this code. JRA. + */ + if(acc->username[strlen(acc->username) - 1] == '$') { + acc->acct_ctrl &= ~ACB_NORMAL; + acc->acct_ctrl |= ACB_WSTRUST; + } + } + + (*count)++; + } + + talloc_free(lines); + + return NT_STATUS_OK; +} diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index c9b121ca774..fc293d5df9e 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -69,8 +69,8 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ &sampass->acct_ctrl, /* w */ &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ &sampass->logon_divs, /* w */ @@ -85,11 +85,11 @@ static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount * } if (lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + return False; } if (nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + return False; } return True; @@ -135,8 +135,8 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ &sampass->acct_ctrl, /* w */ &remove_me, /* d */ &sampass->logon_divs, /* w */ @@ -150,12 +150,12 @@ static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount * return False; } - if (sampass->lm_pw_ptr && lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + if (lm_pw_len != 16) { + return False; } - if (sampass->nt_pw_ptr && nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + if (nt_pw_len != 16) { + return False; } return True; @@ -199,8 +199,8 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * &munged_dial_len, &sampass->munged_dial, /* B */ &sampass->user_rid, /* d */ &sampass->group_rid, /* d */ - &lm_pw_len, &sampass->lm_pw_ptr, /* B */ - &nt_pw_len, &sampass->nt_pw_ptr, /* B */ + &lm_pw_len, sampass->lm_pw.hash, /* B */ + &nt_pw_len, sampass->nt_pw.hash, /* B */ /* Change from V1 is addition of password history field. */ &nt_pw_hist_len, &sampass->nt_pw_hist_ptr, /* B */ &sampass->acct_ctrl, /* w */ @@ -216,12 +216,12 @@ static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount * return False; } - if (sampass->lm_pw_ptr && lm_pw_len != 16) { - sampass->lm_pw_ptr = NULL; + if (lm_pw_len != 16) { + return False; } - if (sampass->nt_pw_ptr && nt_pw_len != 16) { - sampass->nt_pw_ptr = NULL; + if (nt_pw_len != 16) { + return False; } return True; diff --git a/source4/scripting/ejs/smbcalls_ldb.c b/source4/scripting/ejs/smbcalls_ldb.c index aaed14dd8cd..662da0d9718 100644 --- a/source4/scripting/ejs/smbcalls_ldb.c +++ b/source4/scripting/ejs/smbcalls_ldb.c @@ -4,6 +4,7 @@ provide hooks into smbd C calls from ejs scripts Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 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 @@ -247,6 +248,64 @@ static int ejs_ldbErrstring(MprVarHandle eid, int argc, struct MprVar **argv) return 0; } +/* + base64 encode + usage: + dataout = ldb.encode(datain) + */ +static int ejs_base64encode(MprVarHandle eid, int argc, struct MprVar **argv) +{ + char *ret; + DATA_BLOB *blob; + + if (argc != 1) { + ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count"); + return -1; + } + + blob = mprToDataBlob(argv[0]); + ret = ldb_base64_encode(mprMemCtx(), (char *)blob->data, blob->length); + + if (!ret) { + mpr_Return(eid, mprCreateUndefinedVar()); + } else { + mpr_Return(eid, mprString(ret)); + } + + talloc_free(ret); + + return 0; +} + +/* + base64 decode + usage: + dataout = ldb.decode(datain) + */ +static int ejs_base64decode(MprVarHandle eid, int argc, struct MprVar **argv) +{ + char *tmp; + int ret; + + if (argc != 1) { + ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count"); + return -1; + } + + tmp = talloc_strdup(mprMemCtx(), mprToString(argv[0])); + ret = ldb_base64_decode(tmp); + if (ret == -1) { + mpr_Return(eid, mprCreateUndefinedVar()); + } else { + mpr_Return(eid, mprData((uint8_t *)tmp, ret)); + } + + talloc_free(tmp); + + return 0; +} + + /* perform an ldb modify @@ -312,6 +371,8 @@ static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv) mprSetCFunction(ldb, "del", ejs_ldbDelete); mprSetCFunction(ldb, "rename", ejs_ldbRename); mprSetCFunction(ldb, "errstring", ejs_ldbErrstring); + mprSetCFunction(ldb, "encode", ejs_base64encode); + mprSetCFunction(ldb, "decode", ejs_base64decode); mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE)); mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL)); mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE)); diff --git a/source4/scripting/ejs/smbcalls_samba3.c b/source4/scripting/ejs/smbcalls_samba3.c index e6f64810603..eb37168bc89 100644 --- a/source4/scripting/ejs/smbcalls_samba3.c +++ b/source4/scripting/ejs/smbcalls_samba3.c @@ -343,8 +343,8 @@ static struct MprVar mprSamAccounts(struct samba3 *samba3) mprSetVar(&m, "profile_path", mprString(a->profile_path)); mprSetVar(&m, "acct_desc", mprString(a->acct_desc)); mprSetVar(&m, "workstations", mprString(a->workstations)); - - /* FIXME: lm_pw_ptr, nt_pw_ptr */ + mprSetVar(&m, "lm_pw", mprData(a->lm_pw.hash, 16)); + mprSetVar(&m, "nt_pw", mprData(a->nt_pw.hash, 16)); mprAddArray(&mpv, i, m); } diff --git a/source4/scripting/libjs/upgrade.js b/source4/scripting/libjs/upgrade.js index 682721e9315..dbf1c0f2c32 100644 --- a/source4/scripting/libjs/upgrade.js +++ b/source4/scripting/libjs/upgrade.js @@ -101,6 +101,7 @@ samba3RefuseMachinePwdChange: %d function upgrade_sam_account(acc,domaindn) { + var ldb = ldb_init(); var ldif = sprintf( "dn: cn=%s,%s objectClass: top @@ -115,6 +116,8 @@ description: %s primaryGroupID: %d badPwdcount: %d logonCount: %d +ntPwdHash:: %s +lmPwdHash:: %s samba3Domain: %s samba3DirDrive: %s samba3MungedDial: %s @@ -133,9 +136,8 @@ samba3Rid: %d acc.fullname, acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count, acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script, acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time, -acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, acc.user_rid); - - /* FIXME: Passwords */ +acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, acc.user_rid, + ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw)); return ldif; } @@ -295,9 +297,6 @@ var keep = new Array( "obey pam restrictions", "password server", "smb passwd file", - "sam database", - "spoolss database", - "wins database", "private dir", "passwd chat", "password level", @@ -313,17 +312,6 @@ var keep = new Array( "debuglevel", "log file", "smb ports", - "nbt port", - "dgram port", - "cldap port", - "krb5 port", - "web port", - "tls enabled", - "tls keyfile", - "tls certfile", - "tls cafile", - "tls crlfile", - "swat directory", "large readwrite", "max protocol", "min protocol", @@ -344,12 +332,10 @@ var keep = new Array( "use spnego", "server signing", "client signing", - "rpc big endian", "max connections", "paranoid server security", "socket options", "strict sync", - "case insensitive filesystem", "max print jobs", "printable", "print ok", @@ -375,10 +361,7 @@ var keep = new Array( "lock dir", "lock directory", "pid directory", - "js include", - "setup directory", "socket address", - "-valid", "copy", "include", "available", @@ -394,6 +377,23 @@ function upgrade_smbconf(samba3) //FIXME } +function save_smbconf(path,smbconf) +{ + var data = " +# Generated by upgrade.js"; + + for (var i in smbconf.shares) { + var s = smbconf.shares[i]; + data = data + "\n[" + s.name + "]\n"; + for (var j in s.parameters) { + var p = s.parameters[j]; + data = data + "\t" + p.name + " = " + p + "\n"; + } + } + + sys.file_save(path,data); +} + function upgrade(subobj, samba3, message) { var samdb = ldb_init(); @@ -405,7 +405,20 @@ function upgrade(subobj, samba3, message) ok = samdb.modify(ldif); assert(ok); - // FIXME: Enable samba3sam module if original passdb backend was ldap + var ldapurl = undefined; + + // FIXME: figure out ldapurl + + // Enable samba3sam module if original passdb backend was ldap + if (ldapurl != undefined) { + var ldif = sprintf(" +dn: @MAP=samba3sam +@MAP_URL: %s", ldapurl); + samdb.add(ldif); + + samdb.modify("dn: @MODULES +@LIST: samldb,timestamps,objectguid,rdn_name"); + } message("Importing users\n"); for (var i in samba3.samaccounts) { -- 2.34.1