r10596: Move the credentials code into it's own subsystem, and push it under auth/
authorAndrew Bartlett <abartlet@samba.org>
Thu, 29 Sep 2005 00:02:38 +0000 (00:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:39:09 +0000 (13:39 -0500)
Andrew Bartlett
(This used to be commit 2e76a4b8efd59c496d64241d654538d3222545c6)

source4/auth/credentials/credentials.c [moved from source4/lib/credentials.c with 54% similarity]
source4/auth/credentials/credentials_files.c [new file with mode: 0644]
source4/auth/credentials/credentials_krb5.c [new file with mode: 0644]
source4/lib/basic.mk
source4/lib/cmdline/config.mk

similarity index 54%
rename from source4/lib/credentials.c
rename to source4/auth/credentials/credentials.c
index 045047d358a9f6728810f6462aaedf6d299c96b3..11b413b1c6013bf512f265efd6fff2701203eacf 100644 (file)
@@ -1,6 +1,8 @@
 /* 
    Unix SMB/CIFS implementation.
 
+   User credentials handling
+
    Copyright (C) Jelmer Vernooij 2005
    Copyright (C) Tim Potter 2001
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
 */
 
 #include "includes.h"
-#include "system/filesys.h"
-#include "include/secrets.h"
 #include "lib/ldb/include/ldb.h"
 #include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */
-#include "system/kerberos.h"
-#include "auth/kerberos/kerberos.h"
 
 
 /**
@@ -249,207 +247,6 @@ BOOL cli_credentials_set_nt_hash(struct cli_credentials *cred,
        return False;
 }
 
-int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
-                                   enum credentials_obtained obtained)
-{
-       
-       krb5_principal princ;
-       krb5_error_code ret;
-       char *name;
-       char **realm;
-
-       ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, 
-                                   cred->ccache->ccache, &princ);
-
-       if (ret) {
-               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
-               DEBUG(1,("failed to get principal from ccache: %s\n", 
-                        err_mess));
-               talloc_free(err_mess);
-               return ret;
-       }
-       
-       ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name);
-       if (ret) {
-               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
-               DEBUG(1,("failed to unparse principal from ccache: %s\n", 
-                        err_mess));
-               talloc_free(err_mess);
-               return ret;
-       }
-
-       realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ);
-
-       cli_credentials_set_principal(cred, name, obtained);
-
-       free(name);
-
-       krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ);
-
-       cred->ccache_obtained = obtained;
-
-       return 0;
-}
-
-
-static int free_mccache(void *ptr) {
-       struct ccache_container *ccc = ptr;
-       krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache);
-
-       return 0;
-}
-
-static int free_dccache(void *ptr) {
-       struct ccache_container *ccc = ptr;
-       krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
-
-       return 0;
-}
-
-static int cli_credentials_set_ccache(struct cli_credentials *cred, 
-                                     const char *name, 
-                                     enum credentials_obtained obtained)
-{
-       krb5_error_code ret;
-       krb5_principal princ;
-       struct ccache_container *ccc = talloc(cred, struct ccache_container);
-       if (!ccc) {
-               return ENOMEM;
-       }
-
-       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
-       if (ret) {
-               talloc_free(ccc);
-               return ret;
-       }
-       if (name) {
-               ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache);
-               if (ret) {
-                       DEBUG(1,("failed to read krb5 ccache: %s: %s\n", 
-                                name, 
-                                smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
-                       talloc_free(ccc);
-                       return ret;
-               }
-       } else {
-               ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache);
-               if (ret) {
-                       DEBUG(3,("failed to read default krb5 ccache: %s\n", 
-                                smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
-                       talloc_free(ccc);
-                       return ret;
-               }
-       }
-
-       talloc_set_destructor(ccc, free_dccache);
-
-       ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ);
-
-       if (ret) {
-               DEBUG(3,("failed to get principal from default ccache: %s\n", 
-                        smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
-               talloc_free(ccc);               
-               return ret;
-       }
-
-       krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ);
-
-       cred->ccache = ccc;
-       talloc_steal(cred, ccc);
-
-       ret = cli_credentials_set_from_ccache(cred, obtained);
-
-       if (ret) {
-               return ret;
-       }
-
-       return 0;
-}
-
-
-int cli_credentials_new_ccache(struct cli_credentials *cred)
-{
-       krb5_error_code ret;
-       char *rand_string;
-       struct ccache_container *ccc = talloc(cred, struct ccache_container);
-       char *ccache_name;
-       if (!ccc) {
-               return ENOMEM;
-       }
-
-       rand_string = generate_random_str(NULL, 16);
-       if (!rand_string) {
-               talloc_free(ccc);
-               return ENOMEM;
-       }
-
-       ccache_name = talloc_asprintf(ccc, "MEMORY:%s", 
-                             rand_string);
-       talloc_free(rand_string);
-
-       if (!ccache_name) {
-               talloc_free(ccc);
-               return ENOMEM;
-       }
-
-       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
-       if (ret) {
-               talloc_free(ccache_name);
-               talloc_free(ccc);
-               return ret;
-       }
-
-       ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache);
-       if (ret) {
-               DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", 
-                        ccache_name,
-                        smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
-               talloc_free(ccache_name);
-               talloc_free(ccc);
-               return ret;
-       }
-
-       talloc_set_destructor(ccc, free_mccache);
-
-       cred->ccache = ccc;
-       talloc_steal(cred, ccc);
-       talloc_free(ccache_name);
-
-       return ret;
-}
-
-int cli_credentials_get_ccache(struct cli_credentials *cred, 
-                              struct ccache_container **ccc)
-{
-       krb5_error_code ret;
-       
-       if (cred->ccache_obtained >= (MAX(cred->principal_obtained, 
-                                         cred->username_obtained))) {
-               *ccc = cred->ccache;
-               return 0;
-       }
-       if (cli_credentials_is_anonymous(cred)) {
-               return EINVAL;
-       }
-
-       ret = cli_credentials_new_ccache(cred);
-       if (ret) {
-               return ret;
-       }
-       ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache);
-       if (ret) {
-               return ret;
-       }
-       ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained);
-
-       if (ret) {
-               return ret;
-       }
-       *ccc = cred->ccache;
-       return ret;
-}
-
-
 /**
  * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
  * @param cred credentials context
@@ -600,136 +397,6 @@ BOOL cli_credentials_set_workstation_callback(struct cli_credentials *cred,
        return False;
 }
 
-/**
- * Read a file descriptor, and parse it for a password (eg from a file or stdin)
- *
- * @param credentials Credentials structure on which to set the password
- * @param fd open file descriptor to read the password from 
- * @param obtained This enum describes how 'specified' this password is
- */
-
-BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, 
-                                      int fd, enum credentials_obtained obtained)
-{
-       char *p;
-       char pass[128];
-
-       for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
-               p && p - pass < sizeof(pass);) {
-               switch (read(fd, p, 1)) {
-               case 1:
-                       if (*p != '\n' && *p != '\0') {
-                               *++p = '\0'; /* advance p, and null-terminate pass */
-                               break;
-                       }
-               case 0:
-                       if (p - pass) {
-                               *p = '\0'; /* null-terminate it, just in case... */
-                               p = NULL; /* then force the loop condition to become false */
-                               break;
-                       } else {
-                               fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n");
-                               return False;
-                       }
-
-               default:
-                       fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
-                                       fd, strerror(errno));
-                       return False;
-               }
-       }
-
-       cli_credentials_set_password(credentials, pass, obtained);
-       return True;
-}
-
-/**
- * Read a named file, and parse it for a password
- *
- * @param credentials Credentials structure on which to set the password
- * @param file a named file to read the password from 
- * @param obtained This enum describes how 'specified' this password is
- */
-
-BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
-{
-       int fd = open(file, O_RDONLY, 0);
-       BOOL ret;
-
-       if (fd < 0) {
-               fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
-                               file, strerror(errno));
-               return False;
-       }
-
-       ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
-
-       close(fd);
-       
-       return ret;
-}
-
-/**
- * Read a named file, and parse it for username, domain, realm and password
- *
- * @param credentials Credentials structure on which to set the password
- * @param file a named file to read the details from 
- * @param obtained This enum describes how 'specified' this password is
- */
-
-BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) 
-{
-       uint16_t len = 0;
-       char *ptr, *val, *param;
-       char **lines;
-       int i, numlines;
-
-       lines = file_lines_load(file, &numlines, NULL);
-
-       if (lines == NULL)
-       {
-               /* fail if we can't open the credentials file */
-               d_printf("ERROR: Unable to open credentials file!\n");
-               return False;
-       }
-
-       for (i = 0; i < numlines; i++) {
-               len = strlen(lines[i]);
-
-               if (len == 0)
-                       continue;
-
-               /* break up the line into parameter & value.
-                * will need to eat a little whitespace possibly */
-               param = lines[i];
-               if (!(ptr = strchr_m (lines[i], '=')))
-                       continue;
-
-               val = ptr+1;
-               *ptr = '\0';
-
-               /* eat leading white space */
-               while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
-                       val++;
-
-               if (strwicmp("password", param) == 0) {
-                       cli_credentials_set_password(cred, val, obtained);
-               } else if (strwicmp("username", param) == 0) {
-                       cli_credentials_set_username(cred, val, obtained);
-               } else if (strwicmp("domain", param) == 0) {
-                       cli_credentials_set_domain(cred, val, obtained);
-               } else if (strwicmp("realm", param) == 0) {
-                       cli_credentials_set_realm(cred, val, obtained);
-               }
-               memset(lines[i], 0, len);
-       }
-
-       talloc_free(lines);
-
-       return True;
-}
-
-
 /**
  * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
  *
@@ -824,139 +491,6 @@ void cli_credentials_guess(struct cli_credentials *cred)
        cli_credentials_set_ccache(cred, NULL, CRED_GUESS_FILE);
 }
 
-/**
- * Fill in credentials for the machine trust account, from the secrets database.
- * 
- * @param cred Credentials structure to fill in
- * @retval NTSTATUS error detailing any failure
- */
-NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
-{
-       TALLOC_CTX *mem_ctx;
-       
-       struct ldb_context *ldb;
-       int ldb_ret;
-       struct ldb_message **msgs;
-       const char *attrs[] = {
-               "secret",
-               "samAccountName",
-               "flatname",
-               "realm",
-               "secureChannelType",
-               "ntPwdHash",
-               "msDS-KeyVersionNumber",
-               NULL
-       };
-       
-       const char *machine_account;
-       const char *password;
-       const char *domain;
-       const char *realm;
-       enum netr_SchannelType sct;
-       
-       /* ok, we are going to get it now, don't recurse back here */
-       cred->machine_account_pending = False;
-
-       mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
-       /* Local secrets are stored in secrets.ldb */
-       ldb = secrets_db_connect(mem_ctx);
-       if (!ldb) {
-               DEBUG(1, ("Could not open secrets.ldb\n"));
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
-       /* search for the secret record */
-       ldb_ret = gendb_search(ldb,
-                              mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), 
-                              &msgs, attrs,
-                              SECRETS_PRIMARY_DOMAIN_FILTER, 
-                              cli_credentials_get_domain(cred));
-       if (ldb_ret == 0) {
-               DEBUG(1, ("Could not find join record to domain: %s\n",
-                         cli_credentials_get_domain(cred)));
-               talloc_free(mem_ctx);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       } else if (ldb_ret != 1) {
-               DEBUG(1, ("Found more than one (%d) join records to domain: %s\n",
-                         ldb_ret, cli_credentials_get_domain(cred)));
-               talloc_free(mem_ctx);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-       
-       password = ldb_msg_find_string(msgs[0], "secret", NULL);
-
-       machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL);
-
-       if (!machine_account) {
-               DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n",
-                         cli_credentials_get_domain(cred)));
-               talloc_free(mem_ctx);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-       
-       sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0);
-       if (!sct) { 
-               DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n",
-                         machine_account));
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-       
-       if (!password) {
-               const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash");
-               struct samr_Password hash;
-               ZERO_STRUCT(hash);
-               if (nt_password_hash) {
-                       memcpy(hash.hash, nt_password_hash->data, 
-                              MIN(nt_password_hash->length, sizeof(hash.hash)));
-               
-                       cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED);
-               } else {
-               
-                       DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n",
-                                 cli_credentials_get_domain(cred)));
-                       talloc_free(mem_ctx);
-                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               }
-       }
-       
-       cli_credentials_set_secure_channel_type(cred, sct);
-
-       domain = ldb_msg_find_string(msgs[0], "flatname", NULL);
-       if (domain) {
-               cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
-       }
-
-       realm = ldb_msg_find_string(msgs[0], "realm", NULL);
-       if (realm) {
-               cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
-       }
-
-       cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
-       if (password) {
-               cli_credentials_set_password(cred, password, CRED_SPECIFIED);
-       }
-
-       cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0));
-       
-       talloc_free(mem_ctx);
-       
-       return NT_STATUS_OK;
-}
-
-/**
- * Ask that when required, the credentials system will be filled with
- * machine trust account, from the secrets database.
- * 
- * @param cred Credentials structure to fill in
- * @note This function is used to call the above function after, rather 
- *       than during, popt processing.
- *
- */
-void cli_credentials_set_machine_account_pending(struct cli_credentials *cred)
-{
-       cred->machine_account_pending = True;
-}
-
 /**
  * Attach NETLOGON credentials for use with SCHANNEL
  */
@@ -995,25 +529,6 @@ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_creden
        return cred->secure_channel_type;
 }
 
-/** 
- * Set Kerberos KVNO
- */
-
-void cli_credentials_set_kvno(struct cli_credentials *cred,
-                             int kvno)
-{
-       cred->kvno = kvno;
-}
-
-/**
- * Return Kerberos KVNO
- */
-
-int cli_credentials_get_kvno(struct cli_credentials *cred)
-{
-       return cred->kvno;
-}
-
 /**
  * Fill in a credentials structure as the anonymous user
  */
diff --git a/source4/auth/credentials/credentials_files.c b/source4/auth/credentials/credentials_files.c
new file mode 100644 (file)
index 0000000..353ff61
--- /dev/null
@@ -0,0 +1,293 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   User credentials handling (as regards on-disk files)
+
+   Copyright (C) Jelmer Vernooij 2005
+   Copyright (C) Tim Potter 2001
+   Copyright (C) Andrew Bartlett <abartlet@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
+   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"
+#include "lib/ldb/include/ldb.h"
+#include "librpc/gen_ndr/ndr_samr.h" /* for struct samrPassword */
+#include "include/secrets.h"
+#include "system/filesys.h"
+
+/**
+ * Read a file descriptor, and parse it for a password (eg from a file or stdin)
+ *
+ * @param credentials Credentials structure on which to set the password
+ * @param fd open file descriptor to read the password from 
+ * @param obtained This enum describes how 'specified' this password is
+ */
+
+BOOL cli_credentials_parse_password_fd(struct cli_credentials *credentials, 
+                                      int fd, enum credentials_obtained obtained)
+{
+       char *p;
+       char pass[128];
+
+       for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
+               p && p - pass < sizeof(pass);) {
+               switch (read(fd, p, 1)) {
+               case 1:
+                       if (*p != '\n' && *p != '\0') {
+                               *++p = '\0'; /* advance p, and null-terminate pass */
+                               break;
+                       }
+               case 0:
+                       if (p - pass) {
+                               *p = '\0'; /* null-terminate it, just in case... */
+                               p = NULL; /* then force the loop condition to become false */
+                               break;
+                       } else {
+                               fprintf(stderr, "Error reading password from file descriptor %d: %s\n", fd, "empty password\n");
+                               return False;
+                       }
+
+               default:
+                       fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
+                                       fd, strerror(errno));
+                       return False;
+               }
+       }
+
+       cli_credentials_set_password(credentials, pass, obtained);
+       return True;
+}
+
+/**
+ * Read a named file, and parse it for a password
+ *
+ * @param credentials Credentials structure on which to set the password
+ * @param file a named file to read the password from 
+ * @param obtained This enum describes how 'specified' this password is
+ */
+
+BOOL cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
+{
+       int fd = open(file, O_RDONLY, 0);
+       BOOL ret;
+
+       if (fd < 0) {
+               fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n",
+                               file, strerror(errno));
+               return False;
+       }
+
+       ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
+
+       close(fd);
+       
+       return ret;
+}
+
+/**
+ * Read a named file, and parse it for username, domain, realm and password
+ *
+ * @param credentials Credentials structure on which to set the password
+ * @param file a named file to read the details from 
+ * @param obtained This enum describes how 'specified' this password is
+ */
+
+BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained) 
+{
+       uint16_t len = 0;
+       char *ptr, *val, *param;
+       char **lines;
+       int i, numlines;
+
+       lines = file_lines_load(file, &numlines, NULL);
+
+       if (lines == NULL)
+       {
+               /* fail if we can't open the credentials file */
+               d_printf("ERROR: Unable to open credentials file!\n");
+               return False;
+       }
+
+       for (i = 0; i < numlines; i++) {
+               len = strlen(lines[i]);
+
+               if (len == 0)
+                       continue;
+
+               /* break up the line into parameter & value.
+                * will need to eat a little whitespace possibly */
+               param = lines[i];
+               if (!(ptr = strchr_m (lines[i], '=')))
+                       continue;
+
+               val = ptr+1;
+               *ptr = '\0';
+
+               /* eat leading white space */
+               while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
+                       val++;
+
+               if (strwicmp("password", param) == 0) {
+                       cli_credentials_set_password(cred, val, obtained);
+               } else if (strwicmp("username", param) == 0) {
+                       cli_credentials_set_username(cred, val, obtained);
+               } else if (strwicmp("domain", param) == 0) {
+                       cli_credentials_set_domain(cred, val, obtained);
+               } else if (strwicmp("realm", param) == 0) {
+                       cli_credentials_set_realm(cred, val, obtained);
+               }
+               memset(lines[i], 0, len);
+       }
+
+       talloc_free(lines);
+
+       return True;
+}
+
+
+/**
+ * Fill in credentials for the machine trust account, from the secrets database.
+ * 
+ * @param cred Credentials structure to fill in
+ * @retval NTSTATUS error detailing any failure
+ */
+NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
+{
+       TALLOC_CTX *mem_ctx;
+       
+       struct ldb_context *ldb;
+       int ldb_ret;
+       struct ldb_message **msgs;
+       const char *attrs[] = {
+               "secret",
+               "samAccountName",
+               "flatname",
+               "realm",
+               "secureChannelType",
+               "ntPwdHash",
+               "msDS-KeyVersionNumber",
+               NULL
+       };
+       
+       const char *machine_account;
+       const char *password;
+       const char *domain;
+       const char *realm;
+       enum netr_SchannelType sct;
+       
+       /* ok, we are going to get it now, don't recurse back here */
+       cred->machine_account_pending = False;
+
+       mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
+       /* Local secrets are stored in secrets.ldb */
+       ldb = secrets_db_connect(mem_ctx);
+       if (!ldb) {
+               DEBUG(1, ("Could not open secrets.ldb\n"));
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
+       /* search for the secret record */
+       ldb_ret = gendb_search(ldb,
+                              mem_ctx, ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), 
+                              &msgs, attrs,
+                              SECRETS_PRIMARY_DOMAIN_FILTER, 
+                              cli_credentials_get_domain(cred));
+       if (ldb_ret == 0) {
+               DEBUG(1, ("Could not find join record to domain: %s\n",
+                         cli_credentials_get_domain(cred)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       } else if (ldb_ret != 1) {
+               DEBUG(1, ("Found more than one (%d) join records to domain: %s\n",
+                         ldb_ret, cli_credentials_get_domain(cred)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+       
+       password = ldb_msg_find_string(msgs[0], "secret", NULL);
+
+       machine_account = ldb_msg_find_string(msgs[0], "samAccountName", NULL);
+
+       if (!machine_account) {
+               DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n",
+                         cli_credentials_get_domain(cred)));
+               talloc_free(mem_ctx);
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+       
+       sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0);
+       if (!sct) { 
+               DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n",
+                         machine_account));
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+       
+       if (!password) {
+               const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash");
+               struct samr_Password hash;
+               ZERO_STRUCT(hash);
+               if (nt_password_hash) {
+                       memcpy(hash.hash, nt_password_hash->data, 
+                              MIN(nt_password_hash->length, sizeof(hash.hash)));
+               
+                       cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED);
+               } else {
+               
+                       DEBUG(1, ("Could not find 'secret' in join record to domain: %s\n",
+                                 cli_credentials_get_domain(cred)));
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
+       }
+       
+       cli_credentials_set_secure_channel_type(cred, sct);
+
+       domain = ldb_msg_find_string(msgs[0], "flatname", NULL);
+       if (domain) {
+               cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
+       }
+
+       realm = ldb_msg_find_string(msgs[0], "realm", NULL);
+       if (realm) {
+               cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
+       }
+
+       cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
+       if (password) {
+               cli_credentials_set_password(cred, password, CRED_SPECIFIED);
+       }
+
+       cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0));
+       
+       talloc_free(mem_ctx);
+       
+       return NT_STATUS_OK;
+}
+
+/**
+ * Ask that when required, the credentials system will be filled with
+ * machine trust account, from the secrets database.
+ * 
+ * @param cred Credentials structure to fill in
+ * @note This function is used to call the above function after, rather 
+ *       than during, popt processing.
+ *
+ */
+void cli_credentials_set_machine_account_pending(struct cli_credentials *cred)
+{
+       cred->machine_account_pending = True;
+}
+
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
new file mode 100644 (file)
index 0000000..fb32394
--- /dev/null
@@ -0,0 +1,248 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Handle user credentials (as regards krb5)
+
+   Copyright (C) Jelmer Vernooij 2005
+   Copyright (C) Tim Potter 2001
+   Copyright (C) Andrew Bartlett <abartlet@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
+   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"
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+
+
+int cli_credentials_set_from_ccache(struct cli_credentials *cred, 
+                                   enum credentials_obtained obtained)
+{
+       
+       krb5_principal princ;
+       krb5_error_code ret;
+       char *name;
+       char **realm;
+
+       ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context, 
+                                   cred->ccache->ccache, &princ);
+
+       if (ret) {
+               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
+               DEBUG(1,("failed to get principal from ccache: %s\n", 
+                        err_mess));
+               talloc_free(err_mess);
+               return ret;
+       }
+       
+       ret = krb5_unparse_name(cred->ccache->smb_krb5_context->krb5_context, princ, &name);
+       if (ret) {
+               char *err_mess = smb_get_krb5_error_message(cred->ccache->smb_krb5_context->krb5_context, ret, cred);
+               DEBUG(1,("failed to unparse principal from ccache: %s\n", 
+                        err_mess));
+               talloc_free(err_mess);
+               return ret;
+       }
+
+       realm = krb5_princ_realm(cred->ccache->smb_krb5_context->krb5_context, princ);
+
+       cli_credentials_set_principal(cred, name, obtained);
+
+       free(name);
+
+       krb5_free_principal(cred->ccache->smb_krb5_context->krb5_context, princ);
+
+       cred->ccache_obtained = obtained;
+
+       return 0;
+}
+
+
+static int free_mccache(void *ptr) {
+       struct ccache_container *ccc = ptr;
+       krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache);
+
+       return 0;
+}
+
+static int free_dccache(void *ptr) {
+       struct ccache_container *ccc = ptr;
+       krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
+
+       return 0;
+}
+
+int cli_credentials_set_ccache(struct cli_credentials *cred, 
+                              const char *name, 
+                              enum credentials_obtained obtained)
+{
+       krb5_error_code ret;
+       krb5_principal princ;
+       struct ccache_container *ccc = talloc(cred, struct ccache_container);
+       if (!ccc) {
+               return ENOMEM;
+       }
+
+       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
+       if (ret) {
+               talloc_free(ccc);
+               return ret;
+       }
+       if (name) {
+               ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, name, &ccc->ccache);
+               if (ret) {
+                       DEBUG(1,("failed to read krb5 ccache: %s: %s\n", 
+                                name, 
+                                smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
+                       talloc_free(ccc);
+                       return ret;
+               }
+       } else {
+               ret = krb5_cc_default(ccc->smb_krb5_context->krb5_context, &ccc->ccache);
+               if (ret) {
+                       DEBUG(3,("failed to read default krb5 ccache: %s\n", 
+                                smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
+                       talloc_free(ccc);
+                       return ret;
+               }
+       }
+
+       talloc_set_destructor(ccc, free_dccache);
+
+       ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context, ccc->ccache, &princ);
+
+       if (ret) {
+               DEBUG(3,("failed to get principal from default ccache: %s\n", 
+                        smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
+               talloc_free(ccc);               
+               return ret;
+       }
+
+       krb5_free_principal(ccc->smb_krb5_context->krb5_context, princ);
+
+       cred->ccache = ccc;
+       talloc_steal(cred, ccc);
+
+       ret = cli_credentials_set_from_ccache(cred, obtained);
+
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
+
+int cli_credentials_new_ccache(struct cli_credentials *cred)
+{
+       krb5_error_code ret;
+       char *rand_string;
+       struct ccache_container *ccc = talloc(cred, struct ccache_container);
+       char *ccache_name;
+       if (!ccc) {
+               return ENOMEM;
+       }
+
+       rand_string = generate_random_str(NULL, 16);
+       if (!rand_string) {
+               talloc_free(ccc);
+               return ENOMEM;
+       }
+
+       ccache_name = talloc_asprintf(ccc, "MEMORY:%s", 
+                             rand_string);
+       talloc_free(rand_string);
+
+       if (!ccache_name) {
+               talloc_free(ccc);
+               return ENOMEM;
+       }
+
+       ret = smb_krb5_init_context(ccc, &ccc->smb_krb5_context);
+       if (ret) {
+               talloc_free(ccache_name);
+               talloc_free(ccc);
+               return ret;
+       }
+
+       ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache);
+       if (ret) {
+               DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", 
+                        ccache_name,
+                        smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
+               talloc_free(ccache_name);
+               talloc_free(ccc);
+               return ret;
+       }
+
+       talloc_set_destructor(ccc, free_mccache);
+
+       cred->ccache = ccc;
+       talloc_steal(cred, ccc);
+       talloc_free(ccache_name);
+
+       return ret;
+}
+
+int cli_credentials_get_ccache(struct cli_credentials *cred, 
+                              struct ccache_container **ccc)
+{
+       krb5_error_code ret;
+       
+       if (cred->ccache_obtained >= (MAX(cred->principal_obtained, 
+                                         cred->username_obtained))) {
+               *ccc = cred->ccache;
+               return 0;
+       }
+       if (cli_credentials_is_anonymous(cred)) {
+               return EINVAL;
+       }
+
+       ret = cli_credentials_new_ccache(cred);
+       if (ret) {
+               return ret;
+       }
+       ret = kinit_to_ccache(cred, cred, cred->ccache->smb_krb5_context, cred->ccache->ccache);
+       if (ret) {
+               return ret;
+       }
+       ret = cli_credentials_set_from_ccache(cred, cred->principal_obtained);
+
+       if (ret) {
+               return ret;
+       }
+       *ccc = cred->ccache;
+       return ret;
+}
+
+/** 
+ * Set Kerberos KVNO
+ */
+
+void cli_credentials_set_kvno(struct cli_credentials *cred,
+                             int kvno)
+{
+       cred->kvno = kvno;
+}
+
+/**
+ * Return Kerberos KVNO
+ */
+
+int cli_credentials_get_kvno(struct cli_credentials *cred)
+{
+       return cred->kvno;
+}
+
index 3fa9bb354b4266f55e21e37705970aabed54a853..18f6f3aeb9581dd0ba3cdf8cc9e704d9b0ffa76d 100644 (file)
@@ -66,8 +66,7 @@ ADD_OBJ_FILES = \
                lib/mutex.o \
                lib/idtree.o \
                lib/db_wrap.o \
-               lib/gendb.o \
-               lib/credentials.o
+               lib/gendb.o
 REQUIRED_SUBSYSTEMS = \
                LIBLDB CHARSET LIBREPLACE LIBNETIF LIBCRYPTO EXT_LIB_DL LIBTALLOC \
                SOCKET_WRAPPER CONFIG
index 831461b7f3b7109eb880a968e7e1e8e3b5265186..643fa9f1afd670245b7ec6e3ad53539459676f8e 100644 (file)
@@ -3,5 +3,6 @@
 [SUBSYSTEM::LIBCMDLINE_CREDENTIALS]
 ADD_OBJ_FILES = lib/cmdline/getsmbpass.o \
                lib/cmdline/credentials.o
+REQUIRED_SUBSYSTEMS = CREDENTIALS
 # End SUBSYSTEM LIBCMDLINE_CREDENTIALS
 ##############################