/** * Create the requested BUILTIN if it doesn't already exist. This requires * winbindd to be running. * * @param[in] rid BUILTIN rid to create * @return Normal NTSTATUS return. */ static NTSTATUS create_builtin(uint32 rid) { NTSTATUS status = NT_STATUS_OK; struct dom_sid sid; gid_t gid; if (!sid_compose(&sid, &global_sid_Builtin, rid)) { return NT_STATUS_NO_SUCH_ALIAS; } if (!sid_to_gid(&sid, &gid)) { if (!lp_winbind_nested_groups() || !winbind_ping()) { return NT_STATUS_PROTOCOL_UNREACHABLE; } status = pdb_create_builtin_alias(rid); } return status; }
NTSTATUS create_local_token(struct auth_serversupplied_info *server_info) { struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct wbcUnixId *ids; /* * If winbind is not around, we can not make much use of the SIDs the * domain controller provided us with. Likewise if the user name was * mapped to some local unix user. */ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || (server_info->nss_token)) { status = create_token_from_username(server_info, server_info->unix_name, server_info->guest, &server_info->utok.uid, &server_info->utok.gid, &server_info->unix_name, &server_info->security_token); } else { status = create_local_nt_token_from_info3(server_info, server_info->guest, server_info->info3, &server_info->extra, &server_info->security_token); } if (!NT_STATUS_IS_OK(status)) { return status; } /* Convert the SIDs to gids. */ server_info->utok.ngroups = 0; server_info->utok.groups = NULL; t = server_info->security_token; ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, t->num_sids); if (ids == NULL) { return NT_STATUS_NO_MEMORY; } if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) { TALLOC_FREE(ids); return NT_STATUS_NO_MEMORY; } /* Start at index 1, where the groups start. */ for (i=1; i<t->num_sids; i++) { if (ids[i].type != WBC_ID_TYPE_GID) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); continue; } if (!add_gid_to_array_unique(server_info, ids[i].id.gid, &server_info->utok.groups, &server_info->utok.ngroups)) { return NT_STATUS_NO_MEMORY; } } /* * Add the "Unix Group" SID for each gid to catch mapped groups * and their Unix equivalent. This is to solve the backwards * compatibility problem of 'valid users = +ntadmin' where * ntadmin has been paired with "Domain Admins" in the group * mapping table. Otherwise smb.conf would need to be changed * to 'valid user = "******"'. --jerry * * For consistency we also add the "Unix User" SID, * so that the complete unix token is represented within * the nt token. */ uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); for ( i=0; i<server_info->utok.ngroups; i++ ) { gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); } security_token_debug(DBGC_AUTH, 10, server_info->security_token); debug_unix_user_token(DBGC_AUTH, 10, server_info->utok.uid, server_info->utok.gid, server_info->utok.ngroups, server_info->utok.groups); status = log_nt_token(server_info->security_token); return status; }
struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, char **p_save_username, bool create ) { struct passwd *pw = NULL; char *p = NULL; char *username = NULL; /* we only save a copy of the username it has been mangled by winbindd use default domain */ *p_save_username = NULL; /* don't call map_username() here since it has to be done higher up the stack so we don't call it multiple times */ username = talloc_strdup(mem_ctx, domuser); if (!username) { return NULL; } p = strchr_m( username, *lp_winbind_separator() ); /* code for a DOMAIN\user string */ if ( p ) { pw = Get_Pwnam_alloc( mem_ctx, domuser ); if ( pw ) { /* make sure we get the case of the username correct */ /* work around 'winbind use default domain = yes' */ if ( lp_winbind_use_default_domain() && !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { char *domain; /* split the domain and username into 2 strings */ *p = '\0'; domain = username; *p_save_username = talloc_asprintf(mem_ctx, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name); if (!*p_save_username) { TALLOC_FREE(pw); return NULL; } } else { *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); } /* whew -- done! */ return pw; } /* setup for lookup of just the username */ /* remember that p and username are overlapping memory */ p++; username = talloc_strdup(mem_ctx, p); if (!username) { return NULL; } } /* just lookup a plain username */ pw = Get_Pwnam_alloc(mem_ctx, username); /* Create local user if requested but only if winbindd is not running. We need to protect against cases where winbindd is failing and then prematurely creating users in /etc/passwd */ if ( !pw && create && !winbind_ping() ) { /* Don't add a machine account. */ if (username[strlen(username)-1] == '$') return NULL; _smb_create_user(NULL, username, NULL); pw = Get_Pwnam_alloc(mem_ctx, username); } /* one last check for a valid passwd struct */ if (pw) { *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); } return pw; }
BOOL winbindd_running(void) { return winbind_ping(); }
NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, const struct auth_serversupplied_info *server_info, DATA_BLOB *session_key, const char *smb_username, /* for ->sanitized_username, for %U subs */ struct auth_session_info **session_info_out) { struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct auth_session_info *session_info; struct unixid *ids; fstring tmp; /* Ensure we can't possible take a code path leading to a * null defref. */ if (!server_info) { return NT_STATUS_LOGON_FAILURE; } session_info = talloc_zero(mem_ctx, struct auth_session_info); if (!session_info) { return NT_STATUS_NO_MEMORY; } session_info->unix_token = talloc_zero(session_info, struct security_unix_token); if (!session_info->unix_token) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_token->uid = server_info->utok.uid; session_info->unix_token->gid = server_info->utok.gid; session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix); if (!session_info->unix_info) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name); if (!session_info->unix_info->unix_name) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } /* This is a potentially untrusted username for use in %U */ alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp)); session_info->unix_info->sanitized_username = talloc_strdup(session_info->unix_info, tmp); if (session_key) { data_blob_free(&session_info->session_key); session_info->session_key = data_blob_talloc(session_info, session_key->data, session_key->length); if (!session_info->session_key.data && session_key->length) { return NT_STATUS_NO_MEMORY; } } else { session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data, server_info->session_key.length); } /* We need to populate session_info->info with the information found in server_info->info3 */ status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base, server_info->guest == false, &session_info->info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("conversion of info3 into auth_user_info failed!\n")); TALLOC_FREE(session_info); return status; } if (server_info->security_token) { /* Just copy the token, it has already been finalised * (nasty hack to support a cached guest/system session_info */ session_info->security_token = dup_nt_token(session_info, server_info->security_token); if (!session_info->security_token) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_token->ngroups = server_info->utok.ngroups; if (server_info->utok.ngroups != 0) { session_info->unix_token->groups = (gid_t *)talloc_memdup( session_info->unix_token, server_info->utok.groups, sizeof(gid_t)*session_info->unix_token->ngroups); } else { session_info->unix_token->groups = NULL; } *session_info_out = session_info; return NT_STATUS_OK; } /* * If winbind is not around, we can not make much use of the SIDs the * domain controller provided us with. Likewise if the user name was * mapped to some local unix user. */ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || (server_info->nss_token)) { char *found_username = NULL; status = create_token_from_username(session_info, server_info->unix_name, server_info->guest, &session_info->unix_token->uid, &session_info->unix_token->gid, &found_username, &session_info->security_token); if (NT_STATUS_IS_OK(status)) { session_info->unix_info->unix_name = found_username; } } else { status = create_local_nt_token_from_info3(session_info, server_info->guest, server_info->info3, &server_info->extra, &session_info->security_token); } if (!NT_STATUS_IS_OK(status)) { return status; } /* Convert the SIDs to gids. */ session_info->unix_token->ngroups = 0; session_info->unix_token->groups = NULL; t = session_info->security_token; ids = talloc_array(talloc_tos(), struct unixid, t->num_sids); if (ids == NULL) { return NT_STATUS_NO_MEMORY; } if (!sids_to_unixids(t->sids, t->num_sids, ids)) { TALLOC_FREE(ids); return NT_STATUS_NO_MEMORY; } for (i=0; i<t->num_sids; i++) { if (i == 0 && ids[i].type != ID_TYPE_BOTH) { continue; } if (ids[i].type != ID_TYPE_GID && ids[i].type != ID_TYPE_BOTH) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); continue; } if (!add_gid_to_array_unique(session_info, ids[i].id, &session_info->unix_token->groups, &session_info->unix_token->ngroups)) { return NT_STATUS_NO_MEMORY; } } /* * Add the "Unix Group" SID for each gid to catch mapped groups * and their Unix equivalent. This is to solve the backwards * compatibility problem of 'valid users = +ntadmin' where * ntadmin has been paired with "Domain Admins" in the group * mapping table. Otherwise smb.conf would need to be changed * to 'valid user = "******"'. --jerry * * For consistency we also add the "Unix User" SID, * so that the complete unix token is represented within * the nt token. */ uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid); add_sid_to_array_unique(session_info->security_token, &tmp_sid, &session_info->security_token->sids, &session_info->security_token->num_sids); for ( i=0; i<session_info->unix_token->ngroups; i++ ) { gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid); add_sid_to_array_unique(session_info->security_token, &tmp_sid, &session_info->security_token->sids, &session_info->security_token->num_sids); } security_token_debug(DBGC_AUTH, 10, session_info->security_token); debug_unix_user_token(DBGC_AUTH, 10, session_info->unix_token->uid, session_info->unix_token->gid, session_info->unix_token->ngroups, session_info->unix_token->groups); status = log_nt_token(session_info->security_token); if (!NT_STATUS_IS_OK(status)) { return status; } *session_info_out = session_info; return NT_STATUS_OK; }
static int net_idmap_restore(struct net_context *c, int argc, const char **argv) { TALLOC_CTX *ctx; FILE *input; if (c->display_usage) { d_printf(_("Usage:\n" "net idmap restore [inputfile]\n" " Restore ID mappings from file\n" " inputfile\tFile to load ID mappings from. If " "not given, load data from stdin.\n")); return 0; } if (! winbind_ping()) { d_fprintf(stderr, _("To use net idmap Winbindd must be running.\n")); return -1; } ctx = talloc_new(NULL); ALLOC_CHECK(ctx); if (argc == 1) { input = fopen(argv[0], "r"); } else { input = stdin; } while (!feof(input)) { char line[128], sid_string[128]; int len; struct wbcDomainSid sid; enum id_type type = ID_TYPE_NOT_SPECIFIED; unsigned long idval; wbcErr wbc_status; if (fgets(line, 127, input) == NULL) break; len = strlen(line); if ( (len > 0) && (line[len-1] == '\n') ) line[len-1] = '\0'; if (sscanf(line, "GID %lu %128s", &idval, sid_string) == 2) { type = ID_TYPE_GID; } else if (sscanf(line, "UID %lu %128s", &idval, sid_string) == 2) { type = ID_TYPE_UID; } else if (sscanf(line, "USER HWM %lu", &idval) == 1) { /* set uid hwm */ wbc_status = wbcSetUidHwm(idval); if (!WBC_ERROR_IS_OK(wbc_status)) { d_fprintf(stderr, _("Could not set USER HWM: %s\n"), wbcErrorString(wbc_status)); } continue; } else if (sscanf(line, "GROUP HWM %lu", &idval) == 1) { /* set gid hwm */ wbc_status = wbcSetGidHwm(idval); if (!WBC_ERROR_IS_OK(wbc_status)) { d_fprintf(stderr, _("Could not set GROUP HWM: %s\n"), wbcErrorString(wbc_status)); } continue; } else { d_fprintf(stderr, _("ignoring invalid line [%s]\n"), line); continue; } wbc_status = wbcStringToSid(sid_string, &sid); if (!WBC_ERROR_IS_OK(wbc_status)) { d_fprintf(stderr, _("ignoring invalid sid [%s]: %s\n"), sid_string, wbcErrorString(wbc_status)); continue; } if (type == ID_TYPE_UID) { wbc_status = wbcSetUidMapping(idval, &sid); } else { wbc_status = wbcSetGidMapping(idval, &sid); } if (!WBC_ERROR_IS_OK(wbc_status)) { d_fprintf(stderr, _("Could not set mapping of %s %lu to sid %s: %s\n"), (type == ID_TYPE_GID) ? "GID" : "UID", idval, sid_string, wbcErrorString(wbc_status)); continue; } } if (input != stdin) { fclose(input); } talloc_free(ctx); return 0; }