root/source4/dsdb/samdb/samdb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. samdb_relative_path
  2. samdb_credentials
  3. samdb_connect
  4. samdb_copy_template
  5. security_token_create

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    interface functions for the sam database
   5 
   6    Copyright (C) Andrew Tridgell 2004
   7    Copyright (C) Volker Lendecke 2004
   8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
   9 
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "librpc/gen_ndr/ndr_netlogon.h"
  26 #include "librpc/gen_ndr/ndr_misc.h"
  27 #include "librpc/gen_ndr/ndr_security.h"
  28 #include "lib/events/events.h"
  29 #include "lib/ldb/include/ldb.h"
  30 #include "lib/ldb/include/ldb_errors.h"
  31 #include "libcli/security/security.h"
  32 #include "libcli/auth/libcli_auth.h"
  33 #include "libcli/ldap/ldap_ndr.h"
  34 #include "system/time.h"
  35 #include "system/filesys.h"
  36 #include "ldb_wrap.h"
  37 #include "../lib/util/util_ldb.h"
  38 #include "dsdb/samdb/samdb.h"
  39 #include "dsdb/common/flags.h"
  40 #include "param/param.h"
  41 #include "lib/events/events.h"
  42 #include "auth/credentials/credentials.h"
  43 #include "param/secrets.h"
  44 
  45 char *samdb_relative_path(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
  46                                  TALLOC_CTX *mem_ctx, 
  47                                  const char *name) 
  48 {
  49         const char *base_url = 
  50                 (const char *)ldb_get_opaque(ldb, "ldb_url");
  51         char *path, *p, *full_name;
  52         if (name == NULL) {
  53                 return NULL;
  54         }
  55         if (name[0] == 0 || name[0] == '/' || strstr(name, ":/")) {
  56                 return talloc_strdup(mem_ctx, name);
  57         }
  58         path = talloc_strdup(mem_ctx, base_url);
  59         if (path == NULL) {
  60                 return NULL;
  61         }
  62         if ( (p = strrchr(path, '/')) != NULL) {
  63                 p[0] = '\0';
  64                 full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
  65         } else {
  66                 full_name = talloc_asprintf(mem_ctx, "./%s", name);
  67         }
  68         talloc_free(path);
  69         return full_name;
  70 }
  71 
  72 struct cli_credentials *samdb_credentials(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  73                                           struct tevent_context *event_ctx, 
  74                                           struct loadparm_context *lp_ctx) 
  75 {
  76         struct cli_credentials *cred = cli_credentials_init(mem_ctx);
  77         if (!cred) {
  78                 return NULL;
  79         }
  80         cli_credentials_set_conf(cred, lp_ctx);
  81 
  82         /* We don't want to use krb5 to talk to our samdb - recursion
  83          * here would be bad, and this account isn't in the KDC
  84          * anyway */
  85         cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);
  86 
  87         if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL, NULL,
  88                                                          SECRETS_LDAP_FILTER))) {
  89                 /* Perfectly OK - if not against an LDAP backend */
  90                 return NULL;
  91         }
  92         return cred;
  93 }
  94 
  95 /*
  96   connect to the SAM database
  97   return an opaque context pointer on success, or NULL on failure
  98  */
  99 struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 100                                   struct tevent_context *ev_ctx,
 101                                   struct loadparm_context *lp_ctx,
 102                                   struct auth_session_info *session_info)
 103 {
 104         struct ldb_context *ldb;
 105         ldb = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, 
 106                                lp_sam_url(lp_ctx), session_info,
 107                                samdb_credentials(mem_ctx, ev_ctx, lp_ctx), 
 108                                0, NULL);
 109         if (!ldb) {
 110                 return NULL;
 111         }
 112         dsdb_make_schema_global(ldb);
 113         return ldb;
 114 }
 115 
 116 /*
 117   copy from a template record to a message
 118 */
 119 int samdb_copy_template(struct ldb_context *ldb, 
     /* [<][>][^][v][top][bottom][index][help] */
 120                         struct ldb_message *msg, const char *name,
 121                         const char **errstring)
 122 {
 123         struct ldb_result *res;
 124         struct ldb_message *t;
 125         int ret, i, j;
 126         struct ldb_context *templates_ldb;
 127         char *templates_ldb_path; 
 128         struct ldb_dn *basedn;
 129         struct tevent_context *event_ctx;
 130         struct loadparm_context *lp_ctx;
 131 
 132         templates_ldb = talloc_get_type(ldb_get_opaque(ldb, "templates_ldb"), struct ldb_context);
 133 
 134         if (!templates_ldb) {
 135                 templates_ldb_path = samdb_relative_path(ldb, 
 136                                                          msg, 
 137                                                          "templates.ldb");
 138                 if (!templates_ldb_path) {
 139                         *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct path for template db");
 140                         return LDB_ERR_OPERATIONS_ERROR;
 141                 }
 142                 
 143                 event_ctx = ldb_get_event_context(ldb);
 144                 lp_ctx = (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
 145 
 146                 /* FIXME: need to remove this wehn we finally pass the event
 147                  * context around in ldb */
 148                 if (event_ctx == NULL) {
 149                         event_ctx = s4_event_context_init(templates_ldb);
 150                 }
 151 
 152                 templates_ldb = ldb_wrap_connect(ldb, event_ctx, lp_ctx, 
 153                                                 templates_ldb_path, NULL,
 154                                                 NULL, 0, NULL);
 155                 talloc_free(templates_ldb_path);
 156                 if (!templates_ldb) {
 157                         *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to connect to templates db at: %s",
 158                                              templates_ldb_path);
 159                         return LDB_ERR_OPERATIONS_ERROR;
 160                 }
 161                 
 162                 ret = ldb_set_opaque(ldb, "templates_ldb", templates_ldb);
 163                 if (ret != LDB_SUCCESS) {
 164                         return ret;
 165                 }
 166         }
 167         *errstring = NULL;      
 168 
 169         basedn = ldb_dn_new(templates_ldb, ldb, "cn=Templates");
 170         if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) {
 171                 talloc_free(basedn);
 172                 *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: Failed to contruct DN for template '%s'", 
 173                                              name);
 174                 return LDB_ERR_OPERATIONS_ERROR;
 175         }
 176         
 177         /* pull the template record */
 178         ret = ldb_search(templates_ldb, msg, &res, basedn, LDB_SCOPE_BASE, NULL, "distinguishedName=*");
 179         talloc_free(basedn);
 180         if (ret != LDB_SUCCESS) {
 181                 *errstring = talloc_steal(msg, ldb_errstring(templates_ldb));
 182                 return ret;
 183         }
 184         if (res->count != 1) {
 185                 *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1", 
 186                                              name, 
 187                                              res->count);
 188                 talloc_free(res);
 189                 return LDB_ERR_OPERATIONS_ERROR;
 190         }
 191         t = res->msgs[0];
 192 
 193         for (i = 0; i < t->num_elements; i++) {
 194                 struct ldb_message_element *el = &t->elements[i];
 195                 /* some elements should not be copied from the template */
 196                 if (ldb_attr_cmp(el->name, "cn") == 0 ||
 197                     ldb_attr_cmp(el->name, "name") == 0 ||
 198                     ldb_attr_cmp(el->name, "objectClass") == 0 ||
 199                     ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
 200                     ldb_attr_cmp(el->name, "sAMAccountName") == 0 ||
 201                     ldb_attr_cmp(el->name, "distinguishedName") == 0 ||
 202                     ldb_attr_cmp(el->name, "objectGUID") == 0) {
 203                         continue;
 204                 }
 205                 for (j = 0; j < el->num_values; j++) {
 206                         ret = samdb_find_or_add_attribute(ldb, msg, el->name, 
 207                                                           (char *)el->values[j].data);
 208                         if (ret) {
 209                                 *errstring = talloc_asprintf(msg, "Adding attribute %s failed.", el->name);
 210                                 talloc_free(res);
 211                                 return ret;
 212                         }
 213                 }
 214         }
 215 
 216         talloc_free(res);
 217 
 218         return LDB_SUCCESS;
 219 }
 220 
 221 
 222 /****************************************************************************
 223  Create the SID list for this user.
 224 ****************************************************************************/
 225 NTSTATUS security_token_create(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 226                                struct tevent_context *ev_ctx, 
 227                                struct loadparm_context *lp_ctx,
 228                                struct dom_sid *user_sid,
 229                                struct dom_sid *group_sid, 
 230                                int n_groupSIDs,
 231                                struct dom_sid **groupSIDs, 
 232                                bool is_authenticated,
 233                                struct security_token **token)
 234 {
 235         struct security_token *ptoken;
 236         int i;
 237         NTSTATUS status;
 238 
 239         ptoken = security_token_initialise(mem_ctx);
 240         NT_STATUS_HAVE_NO_MEMORY(ptoken);
 241 
 242         ptoken->sids = talloc_array(ptoken, struct dom_sid *, n_groupSIDs + 5);
 243         NT_STATUS_HAVE_NO_MEMORY(ptoken->sids);
 244 
 245         ptoken->user_sid = talloc_reference(ptoken, user_sid);
 246         ptoken->group_sid = talloc_reference(ptoken, group_sid);
 247         ptoken->privilege_mask = 0;
 248 
 249         ptoken->sids[0] = ptoken->user_sid;
 250         ptoken->sids[1] = ptoken->group_sid;
 251 
 252         /*
 253          * Finally add the "standard" SIDs.
 254          * The only difference between guest and "anonymous"
 255          * is the addition of Authenticated_Users.
 256          */
 257         ptoken->sids[2] = dom_sid_parse_talloc(ptoken->sids, SID_WORLD);
 258         NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[2]);
 259         ptoken->sids[3] = dom_sid_parse_talloc(ptoken->sids, SID_NT_NETWORK);
 260         NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[3]);
 261         ptoken->num_sids = 4;
 262 
 263         if (is_authenticated) {
 264                 ptoken->sids[4] = dom_sid_parse_talloc(ptoken->sids, SID_NT_AUTHENTICATED_USERS);
 265                 NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[4]);
 266                 ptoken->num_sids++;
 267         }
 268 
 269         for (i = 0; i < n_groupSIDs; i++) {
 270                 size_t check_sid_idx;
 271                 for (check_sid_idx = 1; 
 272                      check_sid_idx < ptoken->num_sids; 
 273                      check_sid_idx++) {
 274                         if (dom_sid_equal(ptoken->sids[check_sid_idx], groupSIDs[i])) {
 275                                 break;
 276                         }
 277                 }
 278 
 279                 if (check_sid_idx == ptoken->num_sids) {
 280                         ptoken->sids[ptoken->num_sids++] = talloc_reference(ptoken->sids, groupSIDs[i]);
 281                 }
 282         }
 283 
 284         /* setup the privilege mask for this token */
 285         status = samdb_privilege_setup(ev_ctx, lp_ctx, ptoken);
 286         if (!NT_STATUS_IS_OK(status)) {
 287                 talloc_free(ptoken);
 288                 return status;
 289         }
 290 
 291         security_token_debug(10, ptoken);
 292 
 293         *token = ptoken;
 294 
 295         return NT_STATUS_OK;
 296 }

/* [<][>][^][v][top][bottom][index][help] */