r9762: Add support for reading good old smbpasswd files
authorJelmer Vernooij <jelmer@samba.org>
Mon, 29 Aug 2005 22:01:18 +0000 (22:01 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:34:57 +0000 (13:34 -0500)
Fix password support
Make base64 decode/encode functions available to EJS

source/lib/samba3/samba3.h
source/lib/samba3/smbpasswd.c
source/lib/samba3/tdbsam.c
source/scripting/ejs/smbcalls_ldb.c
source/scripting/ejs/smbcalls_samba3.c
source/scripting/libjs/upgrade.js

index 5aba790c4ea0e42327280f9cff28155460e4a383..a41109a145e150ed9d03242b259ec603d64555dd 100644 (file)
@@ -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;
 };
index bcbb5e56d89e331687cf072321503ff3f01e9988..5976d2db572a8037d8fc54f3ab00367d6a39a63d 100644 (file)
@@ -7,6 +7,7 @@
    Modified by Gerald (Jerry) Carter 2000-2001
    Copyright (C) Tim Potter 2001
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+   Copyright (C) Jelmer Vernooij <jelmer@samba.org> 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;
+}
index c9b121ca774d176fa781e664ce64ef48230de583..fc293d5df9ed7cd5e4475eacb089b7561d6e2800 100644 (file)
@@ -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;
index aaed14dd8cd408235e9aae1499ebecaa76129eb7..662da0d9718785468a42cf403ec712d980208a38 100644 (file)
@@ -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));
index e6f6481060376b4166f2af42915883b616173ff3..eb37168bc89b5352aedd7bd4871a93b11fa43409 100644 (file)
@@ -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);
        }
index 682721e9315e95528e10165ebe316a7637bc9580..dbf1c0f2c32a11537782e464f8ddf4ed3227f143 100644 (file)
@@ -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) {