| 1 | /*
 | 
|---|
| 2 |  *  Unix SMB/CIFS implementation.
 | 
|---|
| 3 |  *  Authentication utility functions
 | 
|---|
| 4 |  *  Copyright (C) Andrew Tridgell 1992-1998
 | 
|---|
| 5 |  *  Copyright (C) Andrew Bartlett 2001
 | 
|---|
| 6 |  *  Copyright (C) Jeremy Allison 2000-2001
 | 
|---|
| 7 |  *  Copyright (C) Rafal Szczesniak 2002
 | 
|---|
| 8 |  *  Copyright (C) Volker Lendecke 2006
 | 
|---|
| 9 |  *  Copyright (C) Michael Adam 2007
 | 
|---|
| 10 |  *
 | 
|---|
| 11 |  *  This program is free software; you can redistribute it and/or modify
 | 
|---|
| 12 |  *  it under the terms of the GNU General Public License as published by
 | 
|---|
| 13 |  *  the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 14 |  *  (at your option) any later version.
 | 
|---|
| 15 |  *
 | 
|---|
| 16 |  *  This program is distributed in the hope that it will be useful,
 | 
|---|
| 17 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 |  *  GNU General Public License for more details.
 | 
|---|
| 20 |  *
 | 
|---|
| 21 |  *  You should have received a copy of the GNU General Public License
 | 
|---|
| 22 |  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 23 |  */
 | 
|---|
| 24 | 
 | 
|---|
| 25 | /* functions moved from auth/auth_util.c to minimize linker deps */
 | 
|---|
| 26 | 
 | 
|---|
| 27 | #include "includes.h"
 | 
|---|
| 28 | #include "auth.h"
 | 
|---|
| 29 | #include "secrets.h"
 | 
|---|
| 30 | #include "memcache.h"
 | 
|---|
| 31 | #include "../librpc/gen_ndr/netlogon.h"
 | 
|---|
| 32 | #include "../libcli/security/security.h"
 | 
|---|
| 33 | #include "../lib/util/util_pw.h"
 | 
|---|
| 34 | #include "passdb.h"
 | 
|---|
| 35 | #include "lib/privileges.h"
 | 
|---|
| 36 | 
 | 
|---|
| 37 | /****************************************************************************
 | 
|---|
| 38 |  Check for a SID in an struct security_token
 | 
|---|
| 39 | ****************************************************************************/
 | 
|---|
| 40 | 
 | 
|---|
| 41 | bool nt_token_check_sid ( const struct dom_sid *sid, const struct security_token *token )
 | 
|---|
| 42 | {
 | 
|---|
| 43 |         if ( !sid || !token )
 | 
|---|
| 44 |                 return False;
 | 
|---|
| 45 | 
 | 
|---|
| 46 |         return security_token_has_sid(token, sid);
 | 
|---|
| 47 | }
 | 
|---|
| 48 | 
 | 
|---|
| 49 | bool nt_token_check_domain_rid( struct security_token *token, uint32 rid )
 | 
|---|
| 50 | {
 | 
|---|
| 51 |         struct dom_sid domain_sid;
 | 
|---|
| 52 | 
 | 
|---|
| 53 |         /* if we are a domain member, the get the domain SID, else for
 | 
|---|
| 54 |            a DC or standalone server, use our own SID */
 | 
|---|
| 55 | 
 | 
|---|
| 56 |         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
 | 
|---|
| 57 |                 if ( !secrets_fetch_domain_sid( lp_workgroup(),
 | 
|---|
| 58 |                                                 &domain_sid ) ) {
 | 
|---|
| 59 |                         DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
 | 
|---|
| 60 |                                  "SID for domain [%s]\n", lp_workgroup()));
 | 
|---|
| 61 |                         return False;
 | 
|---|
| 62 |                 }
 | 
|---|
| 63 |         }
 | 
|---|
| 64 |         else
 | 
|---|
| 65 |                 sid_copy( &domain_sid, get_global_sam_sid() );
 | 
|---|
| 66 | 
 | 
|---|
| 67 |         sid_append_rid( &domain_sid, rid );
 | 
|---|
| 68 | 
 | 
|---|
| 69 |         return nt_token_check_sid( &domain_sid, token );\
 | 
|---|
| 70 | }
 | 
|---|
| 71 | 
 | 
|---|
| 72 | /******************************************************************************
 | 
|---|
| 73 |  Create a token for the root user to be used internally by smbd.
 | 
|---|
| 74 |  This is similar to running under the context of the LOCAL_SYSTEM account
 | 
|---|
| 75 |  in Windows.  This is a read-only token.  Do not modify it or free() it.
 | 
|---|
| 76 |  Create a copy if you need to change it.
 | 
|---|
| 77 | ******************************************************************************/
 | 
|---|
| 78 | 
 | 
|---|
| 79 | struct security_token *get_root_nt_token( void )
 | 
|---|
| 80 | {
 | 
|---|
| 81 |         struct security_token *token, *for_cache;
 | 
|---|
| 82 |         struct dom_sid u_sid, g_sid;
 | 
|---|
| 83 |         struct passwd *pw;
 | 
|---|
| 84 |         void *cache_data;
 | 
|---|
| 85 | 
 | 
|---|
| 86 |         cache_data = memcache_lookup_talloc(
 | 
|---|
| 87 |                 NULL, SINGLETON_CACHE_TALLOC,
 | 
|---|
| 88 |                 data_blob_string_const_null("root_nt_token"));
 | 
|---|
| 89 | 
 | 
|---|
| 90 |         if (cache_data != NULL) {
 | 
|---|
| 91 |                 return talloc_get_type_abort(
 | 
|---|
| 92 |                         cache_data, struct security_token);
 | 
|---|
| 93 |         }
 | 
|---|
| 94 | 
 | 
|---|
| 95 |         if ( !(pw = sys_getpwuid(0)) ) {
 | 
|---|
| 96 |                 if ( !(pw = sys_getpwnam("root")) ) {
 | 
|---|
| 97 |                         DEBUG(0,("get_root_nt_token: both sys_getpwuid(0) "
 | 
|---|
| 98 |                                 "and sys_getpwnam(\"root\") failed!\n"));
 | 
|---|
| 99 |                         return NULL;
 | 
|---|
| 100 |                 }
 | 
|---|
| 101 |         }
 | 
|---|
| 102 | 
 | 
|---|
| 103 |         /* get the user and primary group SIDs; although the
 | 
|---|
| 104 |            BUILTIN\Administrators SId is really the one that matters here */
 | 
|---|
| 105 | 
 | 
|---|
| 106 |         uid_to_sid(&u_sid, pw->pw_uid);
 | 
|---|
| 107 |         gid_to_sid(&g_sid, pw->pw_gid);
 | 
|---|
| 108 | 
 | 
|---|
| 109 |         token = create_local_nt_token(talloc_tos(), &u_sid, False,
 | 
|---|
| 110 |                                       1, &global_sid_Builtin_Administrators);
 | 
|---|
| 111 | 
 | 
|---|
| 112 |         security_token_set_privilege(token, SEC_PRIV_DISK_OPERATOR);
 | 
|---|
| 113 | 
 | 
|---|
| 114 |         for_cache = token;
 | 
|---|
| 115 | 
 | 
|---|
| 116 |         memcache_add_talloc(
 | 
|---|
| 117 |                 NULL, SINGLETON_CACHE_TALLOC,
 | 
|---|
| 118 |                 data_blob_string_const_null("root_nt_token"), &for_cache);
 | 
|---|
| 119 | 
 | 
|---|
| 120 |         return token;
 | 
|---|
| 121 | }
 | 
|---|
| 122 | 
 | 
|---|
| 123 | 
 | 
|---|
| 124 | /*
 | 
|---|
| 125 |  * Add alias SIDs from memberships within the partially created token SID list
 | 
|---|
| 126 |  */
 | 
|---|
| 127 | 
 | 
|---|
| 128 | NTSTATUS add_aliases(const struct dom_sid *domain_sid,
 | 
|---|
| 129 |                      struct security_token *token)
 | 
|---|
| 130 | {
 | 
|---|
| 131 |         uint32 *aliases;
 | 
|---|
| 132 |         size_t i, num_aliases;
 | 
|---|
| 133 |         NTSTATUS status;
 | 
|---|
| 134 |         TALLOC_CTX *tmp_ctx;
 | 
|---|
| 135 | 
 | 
|---|
| 136 |         if (!(tmp_ctx = talloc_init("add_aliases"))) {
 | 
|---|
| 137 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 138 |         }
 | 
|---|
| 139 | 
 | 
|---|
| 140 |         aliases = NULL;
 | 
|---|
| 141 |         num_aliases = 0;
 | 
|---|
| 142 | 
 | 
|---|
| 143 |         status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
 | 
|---|
| 144 |                                             token->sids,
 | 
|---|
| 145 |                                             token->num_sids,
 | 
|---|
| 146 |                                             &aliases, &num_aliases);
 | 
|---|
| 147 | 
 | 
|---|
| 148 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 149 |                 DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
 | 
|---|
| 150 |                            nt_errstr(status)));
 | 
|---|
| 151 |                 goto done;
 | 
|---|
| 152 |         }
 | 
|---|
| 153 | 
 | 
|---|
| 154 |         for (i=0; i<num_aliases; i++) {
 | 
|---|
| 155 |                 struct dom_sid alias_sid;
 | 
|---|
| 156 |                 sid_compose(&alias_sid, domain_sid, aliases[i]);
 | 
|---|
| 157 |                 status = add_sid_to_array_unique(token, &alias_sid,
 | 
|---|
| 158 |                                                  &token->sids,
 | 
|---|
| 159 |                                                  &token->num_sids);
 | 
|---|
| 160 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 161 |                         DEBUG(0, ("add_sid_to_array failed\n"));
 | 
|---|
| 162 |                         goto done;
 | 
|---|
| 163 |                 }
 | 
|---|
| 164 |         }
 | 
|---|
| 165 | 
 | 
|---|
| 166 | done:
 | 
|---|
| 167 |         TALLOC_FREE(tmp_ctx);
 | 
|---|
| 168 |         return NT_STATUS_OK;
 | 
|---|
| 169 | }
 | 
|---|
| 170 | 
 | 
|---|
| 171 | /*******************************************************************
 | 
|---|
| 172 | *******************************************************************/
 | 
|---|
| 173 | 
 | 
|---|
| 174 | static NTSTATUS add_builtin_administrators(struct security_token *token,
 | 
|---|
| 175 |                                            const struct dom_sid *dom_sid)
 | 
|---|
| 176 | {
 | 
|---|
| 177 |         struct dom_sid domadm;
 | 
|---|
| 178 |         NTSTATUS status;
 | 
|---|
| 179 | 
 | 
|---|
| 180 |         /* nothing to do if we aren't in a domain */
 | 
|---|
| 181 | 
 | 
|---|
| 182 |         if ( !(IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER) ) {
 | 
|---|
| 183 |                 return NT_STATUS_OK;
 | 
|---|
| 184 |         }
 | 
|---|
| 185 | 
 | 
|---|
| 186 |         /* Find the Domain Admins SID */
 | 
|---|
| 187 | 
 | 
|---|
| 188 |         if ( IS_DC ) {
 | 
|---|
| 189 |                 sid_copy( &domadm, get_global_sam_sid() );
 | 
|---|
| 190 |         } else {
 | 
|---|
| 191 |                 sid_copy(&domadm, dom_sid);
 | 
|---|
| 192 |         }
 | 
|---|
| 193 |         sid_append_rid( &domadm, DOMAIN_RID_ADMINS );
 | 
|---|
| 194 | 
 | 
|---|
| 195 |         /* Add Administrators if the user beloongs to Domain Admins */
 | 
|---|
| 196 | 
 | 
|---|
| 197 |         if ( nt_token_check_sid( &domadm, token ) ) {
 | 
|---|
| 198 |                 status = add_sid_to_array(token,
 | 
|---|
| 199 |                                           &global_sid_Builtin_Administrators,
 | 
|---|
| 200 |                                           &token->sids, &token->num_sids);
 | 
|---|
| 201 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 202 |                         return status;
 | 
|---|
| 203 |                 }
 | 
|---|
| 204 |         }
 | 
|---|
| 205 | 
 | 
|---|
| 206 |         return NT_STATUS_OK;
 | 
|---|
| 207 | }
 | 
|---|
| 208 | 
 | 
|---|
| 209 | static NTSTATUS finalize_local_nt_token(struct security_token *result,
 | 
|---|
| 210 |                                         bool is_guest);
 | 
|---|
| 211 | 
 | 
|---|
| 212 | NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
 | 
|---|
| 213 |                                           bool is_guest,
 | 
|---|
| 214 |                                           struct netr_SamInfo3 *info3,
 | 
|---|
| 215 |                                           struct extra_auth_info *extra,
 | 
|---|
| 216 |                                           struct security_token **ntok)
 | 
|---|
| 217 | {
 | 
|---|
| 218 |         struct security_token *usrtok = NULL;
 | 
|---|
| 219 |         NTSTATUS status;
 | 
|---|
| 220 |         int i;
 | 
|---|
| 221 | 
 | 
|---|
| 222 |         DEBUG(10, ("Create local NT token for %s\n",
 | 
|---|
| 223 |                    info3->base.account_name.string));
 | 
|---|
| 224 | 
 | 
|---|
| 225 |         usrtok = talloc_zero(mem_ctx, struct security_token);
 | 
|---|
| 226 |         if (!usrtok) {
 | 
|---|
| 227 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 228 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 229 |         }
 | 
|---|
| 230 | 
 | 
|---|
| 231 |         /* Add the user and primary group sid FIRST */
 | 
|---|
| 232 |         /* check if the user rid is the special "Domain Guests" rid.
 | 
|---|
| 233 |          * If so pick the first sid for the extra sids instead as it
 | 
|---|
| 234 |          * is a local fake account */
 | 
|---|
| 235 |         usrtok->sids = talloc_array(usrtok, struct dom_sid, 2);
 | 
|---|
| 236 |         if (!usrtok->sids) {
 | 
|---|
| 237 |                 TALLOC_FREE(usrtok);
 | 
|---|
| 238 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 239 |         }
 | 
|---|
| 240 |         usrtok->num_sids = 2;
 | 
|---|
| 241 | 
 | 
|---|
| 242 |         /* USER SID */
 | 
|---|
| 243 |         if (info3->base.rid == (uint32_t)(-1)) {
 | 
|---|
| 244 |                 /* this is a signal the user was fake and generated,
 | 
|---|
| 245 |                  * the actual SID we want to use is stored in the extra
 | 
|---|
| 246 |                  * sids */
 | 
|---|
| 247 |                 if (is_null_sid(&extra->user_sid)) {
 | 
|---|
| 248 |                         /* we couldn't find the user sid, bail out */
 | 
|---|
| 249 |                         DEBUG(3, ("Invalid user SID\n"));
 | 
|---|
| 250 |                         TALLOC_FREE(usrtok);
 | 
|---|
| 251 |                         return NT_STATUS_UNSUCCESSFUL;
 | 
|---|
| 252 |                 }
 | 
|---|
| 253 |                 sid_copy(&usrtok->sids[0], &extra->user_sid);
 | 
|---|
| 254 |         } else {
 | 
|---|
| 255 |                 sid_copy(&usrtok->sids[0], info3->base.domain_sid);
 | 
|---|
| 256 |                 sid_append_rid(&usrtok->sids[0], info3->base.rid);
 | 
|---|
| 257 |         }
 | 
|---|
| 258 | 
 | 
|---|
| 259 |         /* GROUP SID */
 | 
|---|
| 260 |         if (info3->base.primary_gid == (uint32_t)(-1)) {
 | 
|---|
| 261 |                 /* this is a signal the user was fake and generated,
 | 
|---|
| 262 |                  * the actual SID we want to use is stored in the extra
 | 
|---|
| 263 |                  * sids */
 | 
|---|
| 264 |                 if (is_null_sid(&extra->pgid_sid)) {
 | 
|---|
| 265 |                         /* we couldn't find the user sid, bail out */
 | 
|---|
| 266 |                         DEBUG(3, ("Invalid group SID\n"));
 | 
|---|
| 267 |                         TALLOC_FREE(usrtok);
 | 
|---|
| 268 |                         return NT_STATUS_UNSUCCESSFUL;
 | 
|---|
| 269 |                 }
 | 
|---|
| 270 |                 sid_copy(&usrtok->sids[1], &extra->pgid_sid);
 | 
|---|
| 271 |         } else {
 | 
|---|
| 272 |                 sid_copy(&usrtok->sids[1], info3->base.domain_sid);
 | 
|---|
| 273 |                 sid_append_rid(&usrtok->sids[1],
 | 
|---|
| 274 |                                 info3->base.primary_gid);
 | 
|---|
| 275 |         }
 | 
|---|
| 276 | 
 | 
|---|
| 277 |         /* Now the SIDs we got from authentication. These are the ones from
 | 
|---|
| 278 |          * the info3 struct or from the pdb_enum_group_memberships, depending
 | 
|---|
| 279 |          * on who authenticated the user.
 | 
|---|
| 280 |          * Note that we start the for loop at "1" here, we already added the
 | 
|---|
| 281 |          * first group sid as primary above. */
 | 
|---|
| 282 | 
 | 
|---|
| 283 |         for (i = 0; i < info3->base.groups.count; i++) {
 | 
|---|
| 284 |                 struct dom_sid tmp_sid;
 | 
|---|
| 285 | 
 | 
|---|
| 286 |                 sid_copy(&tmp_sid, info3->base.domain_sid);
 | 
|---|
| 287 |                 sid_append_rid(&tmp_sid, info3->base.groups.rids[i].rid);
 | 
|---|
| 288 | 
 | 
|---|
| 289 |                 status = add_sid_to_array_unique(usrtok, &tmp_sid,
 | 
|---|
| 290 |                                                  &usrtok->sids,
 | 
|---|
| 291 |                                                  &usrtok->num_sids);
 | 
|---|
| 292 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 293 |                         DEBUG(3, ("Failed to add SID to nt token\n"));
 | 
|---|
| 294 |                         TALLOC_FREE(usrtok);
 | 
|---|
| 295 |                         return status;
 | 
|---|
| 296 |                 }
 | 
|---|
| 297 |         }
 | 
|---|
| 298 | 
 | 
|---|
| 299 |         /* now also add extra sids if they are not the special user/group
 | 
|---|
| 300 |          * sids */
 | 
|---|
| 301 |         for (i = 0; i < info3->sidcount; i++) {
 | 
|---|
| 302 |                 status = add_sid_to_array_unique(usrtok,
 | 
|---|
| 303 |                                                  info3->sids[i].sid,
 | 
|---|
| 304 |                                                  &usrtok->sids,
 | 
|---|
| 305 |                                                  &usrtok->num_sids);
 | 
|---|
| 306 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 307 |                         DEBUG(3, ("Failed to add SID to nt token\n"));
 | 
|---|
| 308 |                         TALLOC_FREE(usrtok);
 | 
|---|
| 309 |                         return status;
 | 
|---|
| 310 |                 }
 | 
|---|
| 311 |         }
 | 
|---|
| 312 | 
 | 
|---|
| 313 |         status = finalize_local_nt_token(usrtok, is_guest);
 | 
|---|
| 314 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 315 |                 DEBUG(3, ("Failed to finalize nt token\n"));
 | 
|---|
| 316 |                 TALLOC_FREE(usrtok);
 | 
|---|
| 317 |                 return status;
 | 
|---|
| 318 |         }
 | 
|---|
| 319 | 
 | 
|---|
| 320 |         *ntok = usrtok;
 | 
|---|
| 321 |         return NT_STATUS_OK;
 | 
|---|
| 322 | }
 | 
|---|
| 323 | 
 | 
|---|
| 324 | /*******************************************************************
 | 
|---|
| 325 |  Create a NT token for the user, expanding local aliases
 | 
|---|
| 326 | *******************************************************************/
 | 
|---|
| 327 | 
 | 
|---|
| 328 | struct security_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 | 
|---|
| 329 |                                             const struct dom_sid *user_sid,
 | 
|---|
| 330 |                                             bool is_guest,
 | 
|---|
| 331 |                                             int num_groupsids,
 | 
|---|
| 332 |                                             const struct dom_sid *groupsids)
 | 
|---|
| 333 | {
 | 
|---|
| 334 |         struct security_token *result = NULL;
 | 
|---|
| 335 |         int i;
 | 
|---|
| 336 |         NTSTATUS status;
 | 
|---|
| 337 | 
 | 
|---|
| 338 |         DEBUG(10, ("Create local NT token for %s\n",
 | 
|---|
| 339 |                    sid_string_dbg(user_sid)));
 | 
|---|
| 340 | 
 | 
|---|
| 341 |         if (!(result = TALLOC_ZERO_P(mem_ctx, struct security_token))) {
 | 
|---|
| 342 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 343 |                 return NULL;
 | 
|---|
| 344 |         }
 | 
|---|
| 345 | 
 | 
|---|
| 346 |         /* Add the user and primary group sid */
 | 
|---|
| 347 | 
 | 
|---|
| 348 |         status = add_sid_to_array(result, user_sid,
 | 
|---|
| 349 |                                   &result->sids, &result->num_sids);
 | 
|---|
| 350 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 351 |                 TALLOC_FREE(result);
 | 
|---|
| 352 |                 return NULL;
 | 
|---|
| 353 |         }
 | 
|---|
| 354 | 
 | 
|---|
| 355 |         /* For guest, num_groupsids may be zero. */
 | 
|---|
| 356 |         if (num_groupsids) {
 | 
|---|
| 357 |                 status = add_sid_to_array(result, &groupsids[0],
 | 
|---|
| 358 |                                           &result->sids,
 | 
|---|
| 359 |                                           &result->num_sids);
 | 
|---|
| 360 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 361 |                         TALLOC_FREE(result);
 | 
|---|
| 362 |                         return NULL;
 | 
|---|
| 363 |                 }
 | 
|---|
| 364 |         }
 | 
|---|
| 365 | 
 | 
|---|
| 366 |         /* Now the SIDs we got from authentication. These are the ones from
 | 
|---|
| 367 |          * the info3 struct or from the pdb_enum_group_memberships, depending
 | 
|---|
| 368 |          * on who authenticated the user.
 | 
|---|
| 369 |          * Note that we start the for loop at "1" here, we already added the
 | 
|---|
| 370 |          * first group sid as primary above. */
 | 
|---|
| 371 | 
 | 
|---|
| 372 |         for (i=1; i<num_groupsids; i++) {
 | 
|---|
| 373 |                 status = add_sid_to_array_unique(result, &groupsids[i],
 | 
|---|
| 374 |                                                  &result->sids,
 | 
|---|
| 375 |                                                  &result->num_sids);
 | 
|---|
| 376 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 377 |                         TALLOC_FREE(result);
 | 
|---|
| 378 |                         return NULL;
 | 
|---|
| 379 |                 }
 | 
|---|
| 380 |         }
 | 
|---|
| 381 | 
 | 
|---|
| 382 |         status = finalize_local_nt_token(result, is_guest);
 | 
|---|
| 383 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 384 |                 TALLOC_FREE(result);
 | 
|---|
| 385 |                 return NULL;
 | 
|---|
| 386 |         }
 | 
|---|
| 387 | 
 | 
|---|
| 388 |         return result;
 | 
|---|
| 389 | }
 | 
|---|
| 390 | 
 | 
|---|
| 391 | static NTSTATUS finalize_local_nt_token(struct security_token *result,
 | 
|---|
| 392 |                                         bool is_guest)
 | 
|---|
| 393 | {
 | 
|---|
| 394 |         struct dom_sid dom_sid;
 | 
|---|
| 395 |         gid_t gid;
 | 
|---|
| 396 |         NTSTATUS status;
 | 
|---|
| 397 | 
 | 
|---|
| 398 |         /* Add in BUILTIN sids */
 | 
|---|
| 399 | 
 | 
|---|
| 400 |         status = add_sid_to_array(result, &global_sid_World,
 | 
|---|
| 401 |                                   &result->sids, &result->num_sids);
 | 
|---|
| 402 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 403 |                 return status;
 | 
|---|
| 404 |         }
 | 
|---|
| 405 |         status = add_sid_to_array(result, &global_sid_Network,
 | 
|---|
| 406 |                                   &result->sids, &result->num_sids);
 | 
|---|
| 407 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 408 |                 return status;
 | 
|---|
| 409 |         }
 | 
|---|
| 410 | 
 | 
|---|
| 411 |         if (is_guest) {
 | 
|---|
| 412 |                 status = add_sid_to_array(result, &global_sid_Builtin_Guests,
 | 
|---|
| 413 |                                           &result->sids,
 | 
|---|
| 414 |                                           &result->num_sids);
 | 
|---|
| 415 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 416 |                         return status;
 | 
|---|
| 417 |                 }
 | 
|---|
| 418 |         } else {
 | 
|---|
| 419 |                 status = add_sid_to_array(result,
 | 
|---|
| 420 |                                           &global_sid_Authenticated_Users,
 | 
|---|
| 421 |                                           &result->sids,
 | 
|---|
| 422 |                                           &result->num_sids);
 | 
|---|
| 423 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 424 |                         return status;
 | 
|---|
| 425 |                 }
 | 
|---|
| 426 |         }
 | 
|---|
| 427 | 
 | 
|---|
| 428 |         /* Deal with the BUILTIN\Administrators group.  If the SID can
 | 
|---|
| 429 |            be resolved then assume that the add_aliasmem( S-1-5-32 )
 | 
|---|
| 430 |            handled it. */
 | 
|---|
| 431 | 
 | 
|---|
| 432 |         if (!sid_to_gid(&global_sid_Builtin_Administrators, &gid)) {
 | 
|---|
| 433 | 
 | 
|---|
| 434 |                 become_root();
 | 
|---|
| 435 |                 if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
 | 
|---|
| 436 |                         status = NT_STATUS_OK;
 | 
|---|
| 437 |                         DEBUG(3, ("Failed to fetch domain sid for %s\n",
 | 
|---|
| 438 |                                   lp_workgroup()));
 | 
|---|
| 439 |                 } else {
 | 
|---|
| 440 |                         status = create_builtin_administrators(&dom_sid);
 | 
|---|
| 441 |                 }
 | 
|---|
| 442 |                 unbecome_root();
 | 
|---|
| 443 | 
 | 
|---|
| 444 |                 if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
 | 
|---|
| 445 |                         /* Add BUILTIN\Administrators directly to token. */
 | 
|---|
| 446 |                         status = add_builtin_administrators(result, &dom_sid);
 | 
|---|
| 447 |                         if ( !NT_STATUS_IS_OK(status) ) {
 | 
|---|
| 448 |                                 DEBUG(3, ("Failed to check for local "
 | 
|---|
| 449 |                                           "Administrators membership (%s)\n",
 | 
|---|
| 450 |                                           nt_errstr(status)));
 | 
|---|
| 451 |                         }
 | 
|---|
| 452 |                 } else if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 453 |                         DEBUG(2, ("WARNING: Failed to create "
 | 
|---|
| 454 |                                   "BUILTIN\\Administrators group!  Can "
 | 
|---|
| 455 |                                   "Winbind allocate gids?\n"));
 | 
|---|
| 456 |                 }
 | 
|---|
| 457 |         }
 | 
|---|
| 458 | 
 | 
|---|
| 459 |         /* Deal with the BUILTIN\Users group.  If the SID can
 | 
|---|
| 460 |            be resolved then assume that the add_aliasmem( S-1-5-32 )
 | 
|---|
| 461 |            handled it. */
 | 
|---|
| 462 | 
 | 
|---|
| 463 |         if (!sid_to_gid(&global_sid_Builtin_Users, &gid)) {
 | 
|---|
| 464 | 
 | 
|---|
| 465 |                 become_root();
 | 
|---|
| 466 |                 if (!secrets_fetch_domain_sid(lp_workgroup(), &dom_sid)) {
 | 
|---|
| 467 |                         status = NT_STATUS_OK;
 | 
|---|
| 468 |                         DEBUG(3, ("Failed to fetch domain sid for %s\n",
 | 
|---|
| 469 |                                   lp_workgroup()));
 | 
|---|
| 470 |                 } else {
 | 
|---|
| 471 |                         status = create_builtin_users(&dom_sid);
 | 
|---|
| 472 |                 }
 | 
|---|
| 473 |                 unbecome_root();
 | 
|---|
| 474 | 
 | 
|---|
| 475 |                 if (!NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE) &&
 | 
|---|
| 476 |                     !NT_STATUS_IS_OK(status))
 | 
|---|
| 477 |                 {
 | 
|---|
| 478 |                         DEBUG(2, ("WARNING: Failed to create BUILTIN\\Users group! "
 | 
|---|
| 479 |                                   "Can Winbind allocate gids?\n"));
 | 
|---|
| 480 |                 }
 | 
|---|
| 481 |         }
 | 
|---|
| 482 | 
 | 
|---|
| 483 |         /* Deal with local groups */
 | 
|---|
| 484 | 
 | 
|---|
| 485 |         if (lp_winbind_nested_groups()) {
 | 
|---|
| 486 | 
 | 
|---|
| 487 |                 become_root();
 | 
|---|
| 488 | 
 | 
|---|
| 489 |                 /* Now add the aliases. First the one from our local SAM */
 | 
|---|
| 490 | 
 | 
|---|
| 491 |                 status = add_aliases(get_global_sam_sid(), result);
 | 
|---|
| 492 | 
 | 
|---|
| 493 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 494 |                         unbecome_root();
 | 
|---|
| 495 |                         return status;
 | 
|---|
| 496 |                 }
 | 
|---|
| 497 | 
 | 
|---|
| 498 |                 /* Finally the builtin ones */
 | 
|---|
| 499 | 
 | 
|---|
| 500 |                 status = add_aliases(&global_sid_Builtin, result);
 | 
|---|
| 501 | 
 | 
|---|
| 502 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 503 |                         unbecome_root();
 | 
|---|
| 504 |                         return status;
 | 
|---|
| 505 |                 }
 | 
|---|
| 506 | 
 | 
|---|
| 507 |                 unbecome_root();
 | 
|---|
| 508 |         }
 | 
|---|
| 509 | 
 | 
|---|
| 510 |         /* Add privileges based on current user sids */
 | 
|---|
| 511 | 
 | 
|---|
| 512 |         get_privileges_for_sids(&result->privilege_mask, result->sids,
 | 
|---|
| 513 |                                 result->num_sids);
 | 
|---|
| 514 | 
 | 
|---|
| 515 |         return NT_STATUS_OK;
 | 
|---|
| 516 | }
 | 
|---|
| 517 | 
 | 
|---|
| 518 | /****************************************************************************
 | 
|---|
| 519 |  prints a UNIX 'token' to debug output.
 | 
|---|
| 520 | ****************************************************************************/
 | 
|---|
| 521 | 
 | 
|---|
| 522 | void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
 | 
|---|
| 523 |                            int n_groups, gid_t *groups)
 | 
|---|
| 524 | {
 | 
|---|
| 525 |         int     i;
 | 
|---|
| 526 |         DEBUGC(dbg_class, dbg_lev,
 | 
|---|
| 527 |                ("UNIX token of user %ld\n", (long int)uid));
 | 
|---|
| 528 | 
 | 
|---|
| 529 |         DEBUGADDC(dbg_class, dbg_lev,
 | 
|---|
| 530 |                   ("Primary group is %ld and contains %i supplementary "
 | 
|---|
| 531 |                    "groups\n", (long int)gid, n_groups));
 | 
|---|
| 532 |         for (i = 0; i < n_groups; i++)
 | 
|---|
| 533 |                 DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
 | 
|---|
| 534 |                         (long int)groups[i]));
 | 
|---|
| 535 | }
 | 
|---|
| 536 | 
 | 
|---|
| 537 | /*
 | 
|---|
| 538 |  * Create an artificial NT token given just a username. (Initially intended
 | 
|---|
| 539 |  * for force user)
 | 
|---|
| 540 |  *
 | 
|---|
| 541 |  * We go through lookup_name() to avoid problems we had with 'winbind use
 | 
|---|
| 542 |  * default domain'.
 | 
|---|
| 543 |  *
 | 
|---|
| 544 |  * We have 3 cases:
 | 
|---|
| 545 |  *
 | 
|---|
| 546 |  * unmapped unix users: Go directly to nss to find the user's group.
 | 
|---|
| 547 |  *
 | 
|---|
| 548 |  * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
 | 
|---|
| 549 |  *
 | 
|---|
| 550 |  * If the user is provided by winbind, the primary gid is set to "domain
 | 
|---|
| 551 |  * users" of the user's domain. For an explanation why this is necessary, see
 | 
|---|
| 552 |  * the thread starting at
 | 
|---|
| 553 |  * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
 | 
|---|
| 554 |  */
 | 
|---|
| 555 | 
 | 
|---|
| 556 | NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
 | 
|---|
| 557 |                                     bool is_guest,
 | 
|---|
| 558 |                                     uid_t *uid, gid_t *gid,
 | 
|---|
| 559 |                                     char **found_username,
 | 
|---|
| 560 |                                     struct security_token **token)
 | 
|---|
| 561 | {
 | 
|---|
| 562 |         NTSTATUS result = NT_STATUS_NO_SUCH_USER;
 | 
|---|
| 563 |         TALLOC_CTX *tmp_ctx = talloc_stackframe();
 | 
|---|
| 564 |         struct dom_sid user_sid;
 | 
|---|
| 565 |         enum lsa_SidType type;
 | 
|---|
| 566 |         gid_t *gids;
 | 
|---|
| 567 |         struct dom_sid *group_sids;
 | 
|---|
| 568 |         struct dom_sid unix_group_sid;
 | 
|---|
| 569 |         uint32_t num_group_sids;
 | 
|---|
| 570 |         uint32_t num_gids;
 | 
|---|
| 571 |         uint32_t i;
 | 
|---|
| 572 | 
 | 
|---|
| 573 |         if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
 | 
|---|
| 574 |                          NULL, NULL, &user_sid, &type)) {
 | 
|---|
| 575 |                 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
 | 
|---|
| 576 |                 goto done;
 | 
|---|
| 577 |         }
 | 
|---|
| 578 | 
 | 
|---|
| 579 |         if (type != SID_NAME_USER) {
 | 
|---|
| 580 |                 DEBUG(1, ("%s is a %s, not a user\n", username,
 | 
|---|
| 581 |                           sid_type_lookup(type)));
 | 
|---|
| 582 |                 goto done;
 | 
|---|
| 583 |         }
 | 
|---|
| 584 | 
 | 
|---|
| 585 |         if (sid_check_is_in_our_domain(&user_sid)) {
 | 
|---|
| 586 |                 bool ret;
 | 
|---|
| 587 |                 uint32_t pdb_num_group_sids;
 | 
|---|
| 588 |                 /* This is a passdb user, so ask passdb */
 | 
|---|
| 589 | 
 | 
|---|
| 590 |                 struct samu *sam_acct = NULL;
 | 
|---|
| 591 | 
 | 
|---|
| 592 |                 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
 | 
|---|
| 593 |                         result = NT_STATUS_NO_MEMORY;
 | 
|---|
| 594 |                         goto done;
 | 
|---|
| 595 |                 }
 | 
|---|
| 596 | 
 | 
|---|
| 597 |                 become_root();
 | 
|---|
| 598 |                 ret = pdb_getsampwsid(sam_acct, &user_sid);
 | 
|---|
| 599 |                 unbecome_root();
 | 
|---|
| 600 | 
 | 
|---|
| 601 |                 if (!ret) {
 | 
|---|
| 602 |                         DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
 | 
|---|
| 603 |                                   sid_string_dbg(&user_sid), username));
 | 
|---|
| 604 |                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
 | 
|---|
| 605 |                         goto unix_user;
 | 
|---|
| 606 |                 }
 | 
|---|
| 607 | 
 | 
|---|
| 608 |                 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
 | 
|---|
| 609 |                                                     &group_sids, &gids,
 | 
|---|
| 610 |                                                     &pdb_num_group_sids);
 | 
|---|
| 611 |                 if (!NT_STATUS_IS_OK(result)) {
 | 
|---|
| 612 |                         DEBUG(1, ("enum_group_memberships failed for %s (%s): "
 | 
|---|
| 613 |                                   "%s\n", username, sid_string_dbg(&user_sid),
 | 
|---|
| 614 |                                   nt_errstr(result)));
 | 
|---|
| 615 |                         DEBUGADD(1, ("Fall back to unix user %s\n", username));
 | 
|---|
| 616 |                         goto unix_user;
 | 
|---|
| 617 |                 }
 | 
|---|
| 618 |                 num_group_sids = pdb_num_group_sids;
 | 
|---|
| 619 | 
 | 
|---|
| 620 |                 /* see the smb_panic() in pdb_default_enum_group_memberships */
 | 
|---|
| 621 |                 SMB_ASSERT(num_group_sids > 0);
 | 
|---|
| 622 | 
 | 
|---|
| 623 |                 *gid = gids[0];
 | 
|---|
| 624 | 
 | 
|---|
| 625 |                 /* Ensure we're returning the found_username on the right context. */
 | 
|---|
| 626 |                 *found_username = talloc_strdup(mem_ctx,
 | 
|---|
| 627 |                                                 pdb_get_username(sam_acct));
 | 
|---|
| 628 | 
 | 
|---|
| 629 |                 /*
 | 
|---|
| 630 |                  * If the SID from lookup_name() was the guest sid, passdb knows
 | 
|---|
| 631 |                  * about the mapping of guest sid to lp_guestaccount()
 | 
|---|
| 632 |                  * username and will return the unix_pw info for a guest
 | 
|---|
| 633 |                  * user. Use it if it's there, else lookup the *uid details
 | 
|---|
| 634 |                  * using Get_Pwnam_alloc(). See bug #6291 for details. JRA.
 | 
|---|
| 635 |                  */
 | 
|---|
| 636 | 
 | 
|---|
| 637 |                 /* We must always assign the *uid. */
 | 
|---|
| 638 |                 if (sam_acct->unix_pw == NULL) {
 | 
|---|
| 639 |                         struct passwd *pwd = Get_Pwnam_alloc(sam_acct, *found_username );
 | 
|---|
| 640 |                         if (!pwd) {
 | 
|---|
| 641 |                                 DEBUG(10, ("Get_Pwnam_alloc failed for %s\n",
 | 
|---|
| 642 |                                         *found_username));
 | 
|---|
| 643 |                                 result = NT_STATUS_NO_SUCH_USER;
 | 
|---|
| 644 |                                 goto done;
 | 
|---|
| 645 |                         }
 | 
|---|
| 646 |                         result = samu_set_unix(sam_acct, pwd );
 | 
|---|
| 647 |                         if (!NT_STATUS_IS_OK(result)) {
 | 
|---|
| 648 |                                 DEBUG(10, ("samu_set_unix failed for %s\n",
 | 
|---|
| 649 |                                         *found_username));
 | 
|---|
| 650 |                                 result = NT_STATUS_NO_SUCH_USER;
 | 
|---|
| 651 |                                 goto done;
 | 
|---|
| 652 |                         }
 | 
|---|
| 653 |                 }
 | 
|---|
| 654 |                 *uid = sam_acct->unix_pw->pw_uid;
 | 
|---|
| 655 | 
 | 
|---|
| 656 |         } else  if (sid_check_is_in_unix_users(&user_sid)) {
 | 
|---|
| 657 |                 uint32_t getgroups_num_group_sids;
 | 
|---|
| 658 |                 /* This is a unix user not in passdb. We need to ask nss
 | 
|---|
| 659 |                  * directly, without consulting passdb */
 | 
|---|
| 660 | 
 | 
|---|
| 661 |                 struct passwd *pass;
 | 
|---|
| 662 | 
 | 
|---|
| 663 |                 /*
 | 
|---|
| 664 |                  * This goto target is used as a fallback for the passdb
 | 
|---|
| 665 |                  * case. The concrete bug report is when passdb gave us an
 | 
|---|
| 666 |                  * unmapped gid.
 | 
|---|
| 667 |                  */
 | 
|---|
| 668 | 
 | 
|---|
| 669 |         unix_user:
 | 
|---|
| 670 | 
 | 
|---|
| 671 |                 if (!sid_to_uid(&user_sid, uid)) {
 | 
|---|
| 672 |                         DEBUG(1, ("unix_user case, sid_to_uid for %s (%s) failed\n",
 | 
|---|
| 673 |                                   username, sid_string_dbg(&user_sid)));
 | 
|---|
| 674 |                         result = NT_STATUS_NO_SUCH_USER;
 | 
|---|
| 675 |                         goto done;
 | 
|---|
| 676 |                 }
 | 
|---|
| 677 | 
 | 
|---|
| 678 |                 uid_to_unix_users_sid(*uid, &user_sid);
 | 
|---|
| 679 | 
 | 
|---|
| 680 |                 pass = getpwuid_alloc(tmp_ctx, *uid);
 | 
|---|
| 681 |                 if (pass == NULL) {
 | 
|---|
| 682 |                         DEBUG(1, ("getpwuid(%u) for user %s failed\n",
 | 
|---|
| 683 |                                   (unsigned int)*uid, username));
 | 
|---|
| 684 |                         goto done;
 | 
|---|
| 685 |                 }
 | 
|---|
| 686 | 
 | 
|---|
| 687 |                 if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
 | 
|---|
| 688 |                                          &gids, &getgroups_num_group_sids)) {
 | 
|---|
| 689 |                         DEBUG(1, ("getgroups_unix_user for user %s failed\n",
 | 
|---|
| 690 |                                   username));
 | 
|---|
| 691 |                         goto done;
 | 
|---|
| 692 |                 }
 | 
|---|
| 693 |                 num_group_sids = getgroups_num_group_sids;
 | 
|---|
| 694 | 
 | 
|---|
| 695 |                 if (num_group_sids) {
 | 
|---|
| 696 |                         group_sids = TALLOC_ARRAY(tmp_ctx, struct dom_sid, num_group_sids);
 | 
|---|
| 697 |                         if (group_sids == NULL) {
 | 
|---|
| 698 |                                 DEBUG(1, ("TALLOC_ARRAY failed\n"));
 | 
|---|
| 699 |                                 result = NT_STATUS_NO_MEMORY;
 | 
|---|
| 700 |                                 goto done;
 | 
|---|
| 701 |                         }
 | 
|---|
| 702 |                 } else {
 | 
|---|
| 703 |                         group_sids = NULL;
 | 
|---|
| 704 |                 }
 | 
|---|
| 705 | 
 | 
|---|
| 706 |                 for (i=0; i<num_group_sids; i++) {
 | 
|---|
| 707 |                         gid_to_sid(&group_sids[i], gids[i]);
 | 
|---|
| 708 |                 }
 | 
|---|
| 709 | 
 | 
|---|
| 710 |                 /* In getgroups_unix_user we always set the primary gid */
 | 
|---|
| 711 |                 SMB_ASSERT(num_group_sids > 0);
 | 
|---|
| 712 | 
 | 
|---|
| 713 |                 *gid = gids[0];
 | 
|---|
| 714 | 
 | 
|---|
| 715 |                 /* Ensure we're returning the found_username on the right context. */
 | 
|---|
| 716 |                 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
 | 
|---|
| 717 |         } else {
 | 
|---|
| 718 | 
 | 
|---|
| 719 |                 /* This user is from winbind, force the primary gid to the
 | 
|---|
| 720 |                  * user's "domain users" group. Under certain circumstances
 | 
|---|
| 721 |                  * (user comes from NT4), this might be a loss of
 | 
|---|
| 722 |                  * information. But we can not rely on winbind getting the
 | 
|---|
| 723 |                  * correct info. AD might prohibit winbind looking up that
 | 
|---|
| 724 |                  * information. */
 | 
|---|
| 725 | 
 | 
|---|
| 726 |                 /* We must always assign the *uid. */
 | 
|---|
| 727 |                 if (!sid_to_uid(&user_sid, uid)) {
 | 
|---|
| 728 |                         DEBUG(1, ("winbindd case, sid_to_uid for %s (%s) failed\n",
 | 
|---|
| 729 |                                   username, sid_string_dbg(&user_sid)));
 | 
|---|
| 730 |                         result = NT_STATUS_NO_SUCH_USER;
 | 
|---|
| 731 |                         goto done;
 | 
|---|
| 732 |                 }
 | 
|---|
| 733 | 
 | 
|---|
| 734 |                 num_group_sids = 1;
 | 
|---|
| 735 |                 group_sids = TALLOC_ARRAY(tmp_ctx, struct dom_sid, num_group_sids);
 | 
|---|
| 736 |                 if (group_sids == NULL) {
 | 
|---|
| 737 |                         DEBUG(1, ("TALLOC_ARRAY failed\n"));
 | 
|---|
| 738 |                         result = NT_STATUS_NO_MEMORY;
 | 
|---|
| 739 |                         goto done;
 | 
|---|
| 740 |                 }
 | 
|---|
| 741 | 
 | 
|---|
| 742 |                 sid_copy(&group_sids[0], &user_sid);
 | 
|---|
| 743 |                 sid_split_rid(&group_sids[0], NULL);
 | 
|---|
| 744 |                 sid_append_rid(&group_sids[0], DOMAIN_RID_USERS);
 | 
|---|
| 745 | 
 | 
|---|
| 746 |                 if (!sid_to_gid(&group_sids[0], gid)) {
 | 
|---|
| 747 |                         DEBUG(1, ("sid_to_gid(%s) failed\n",
 | 
|---|
| 748 |                                   sid_string_dbg(&group_sids[0])));
 | 
|---|
| 749 |                         goto done;
 | 
|---|
| 750 |                 }
 | 
|---|
| 751 | 
 | 
|---|
| 752 |                 gids = gid;
 | 
|---|
| 753 | 
 | 
|---|
| 754 |                 /* Ensure we're returning the found_username on the right context. */
 | 
|---|
| 755 |                 *found_username = talloc_strdup(mem_ctx, username);
 | 
|---|
| 756 |         }
 | 
|---|
| 757 | 
 | 
|---|
| 758 |         /* Add the "Unix Group" SID for each gid to catch mapped groups
 | 
|---|
| 759 |            and their Unix equivalent.  This is to solve the backwards
 | 
|---|
| 760 |            compatibility problem of 'valid users = +ntadmin' where
 | 
|---|
| 761 |            ntadmin has been paired with "Domain Admins" in the group
 | 
|---|
| 762 |            mapping table.  Otherwise smb.conf would need to be changed
 | 
|---|
| 763 |            to 'valid user = "Domain Admins"'.  --jerry */
 | 
|---|
| 764 | 
 | 
|---|
| 765 |         num_gids = num_group_sids;
 | 
|---|
| 766 |         for ( i=0; i<num_gids; i++ ) {
 | 
|---|
| 767 |                 gid_t high, low;
 | 
|---|
| 768 | 
 | 
|---|
| 769 |                 /* don't pickup anything managed by Winbind */
 | 
|---|
| 770 | 
 | 
|---|
| 771 |                 if ( lp_idmap_gid(&low, &high) && (gids[i] >= low) && (gids[i] <= high) )
 | 
|---|
| 772 |                         continue;
 | 
|---|
| 773 | 
 | 
|---|
| 774 |                 gid_to_unix_groups_sid(gids[i], &unix_group_sid);
 | 
|---|
| 775 | 
 | 
|---|
| 776 |                 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
 | 
|---|
| 777 |                                                  &group_sids, &num_group_sids);
 | 
|---|
| 778 |                 if (!NT_STATUS_IS_OK(result)) {
 | 
|---|
| 779 |                         goto done;
 | 
|---|
| 780 |                 }
 | 
|---|
| 781 |         }
 | 
|---|
| 782 | 
 | 
|---|
| 783 |         /* Ensure we're creating the nt_token on the right context. */
 | 
|---|
| 784 |         *token = create_local_nt_token(mem_ctx, &user_sid,
 | 
|---|
| 785 |                                        is_guest, num_group_sids, group_sids);
 | 
|---|
| 786 | 
 | 
|---|
| 787 |         if ((*token == NULL) || (*found_username == NULL)) {
 | 
|---|
| 788 |                 result = NT_STATUS_NO_MEMORY;
 | 
|---|
| 789 |                 goto done;
 | 
|---|
| 790 |         }
 | 
|---|
| 791 | 
 | 
|---|
| 792 |         result = NT_STATUS_OK;
 | 
|---|
| 793 |  done:
 | 
|---|
| 794 |         TALLOC_FREE(tmp_ctx);
 | 
|---|
| 795 |         return result;
 | 
|---|
| 796 | }
 | 
|---|
| 797 | 
 | 
|---|
| 798 | /***************************************************************************
 | 
|---|
| 799 |  Build upon create_token_from_username:
 | 
|---|
| 800 | 
 | 
|---|
| 801 |  Expensive helper function to figure out whether a user given its name is
 | 
|---|
| 802 |  member of a particular group.
 | 
|---|
| 803 | ***************************************************************************/
 | 
|---|
| 804 | 
 | 
|---|
| 805 | bool user_in_group_sid(const char *username, const struct dom_sid *group_sid)
 | 
|---|
| 806 | {
 | 
|---|
| 807 |         NTSTATUS status;
 | 
|---|
| 808 |         uid_t uid;
 | 
|---|
| 809 |         gid_t gid;
 | 
|---|
| 810 |         char *found_username;
 | 
|---|
| 811 |         struct security_token *token;
 | 
|---|
| 812 |         bool result;
 | 
|---|
| 813 |         TALLOC_CTX *mem_ctx = talloc_stackframe();
 | 
|---|
| 814 | 
 | 
|---|
| 815 |         status = create_token_from_username(mem_ctx, username, False,
 | 
|---|
| 816 |                                             &uid, &gid, &found_username,
 | 
|---|
| 817 |                                             &token);
 | 
|---|
| 818 | 
 | 
|---|
| 819 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 820 |                 DEBUG(10, ("could not create token for %s\n", username));
 | 
|---|
| 821 |                 TALLOC_FREE(mem_ctx);
 | 
|---|
| 822 |                 return False;
 | 
|---|
| 823 |         }
 | 
|---|
| 824 | 
 | 
|---|
| 825 |         result = security_token_has_sid(token, group_sid);
 | 
|---|
| 826 | 
 | 
|---|
| 827 |         TALLOC_FREE(mem_ctx);
 | 
|---|
| 828 |         return result;
 | 
|---|
| 829 | }
 | 
|---|
| 830 | 
 | 
|---|
| 831 | bool user_in_group(const char *username, const char *groupname)
 | 
|---|
| 832 | {
 | 
|---|
| 833 |         TALLOC_CTX *mem_ctx = talloc_stackframe();
 | 
|---|
| 834 |         struct dom_sid group_sid;
 | 
|---|
| 835 |         bool ret;
 | 
|---|
| 836 | 
 | 
|---|
| 837 |         ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
 | 
|---|
| 838 |                           NULL, NULL, &group_sid, NULL);
 | 
|---|
| 839 |         TALLOC_FREE(mem_ctx);
 | 
|---|
| 840 | 
 | 
|---|
| 841 |         if (!ret) {
 | 
|---|
| 842 |                 DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
 | 
|---|
| 843 |                 return False;
 | 
|---|
| 844 |         }
 | 
|---|
| 845 | 
 | 
|---|
| 846 |         return user_in_group_sid(username, &group_sid);
 | 
|---|
| 847 | }
 | 
|---|
| 848 | 
 | 
|---|
| 849 | /* END */
 | 
|---|