DOM_SID user_sid;
DOM_SID group_sid;
- struct passwd *passwd;
-
- unid_t u_id, g_id;
uid_t uid;
gid_t gid;
- int u_type, g_type;
int n_lgroupSIDs;
DOM_SID *lgroupSIDs = NULL;
/* If the server didn't give us one, just use the one we sent them */
domain = domain;
}
-
- u_type = ID_USERID;
- g_type = ID_GROUPID;
-
- /* we are trying to check that idmap isn't stuffing us over - does this
- user actually exist? */
- if (NT_STATUS_IS_OK(idmap_get_id_from_sid(&u_id, &u_type, &user_sid))
- && NT_STATUS_IS_OK(idmap_get_id_from_sid(&g_id, &g_type, &group_sid))
- && ((passwd = getpwuid_alloc(u_id.uid)))) {
-
- nt_status = pdb_init_sam_pw(&sam_account, passwd);
-
- uid = passwd->pw_uid;
- gid = passwd->pw_gid;
-
- /* we should check this is the same name */
- found_username = talloc_strdup(mem_ctx, passwd->pw_name);
-
- passwd_free(&passwd);
- } else {
-
- /* User not from winbind - try and find them by getpwnam() */
- nt_status = fill_sam_account(mem_ctx, nt_domain,
- internal_username,
- &found_username,
- &uid, &gid,
- &sam_account);
-
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
- DEBUG(3,("User %s does not exist, trying to add it\n",
- internal_username));
- auth_add_user_script(nt_domain, internal_username);
- nt_status = fill_sam_account(mem_ctx, nt_domain,
- internal_username,
- &found_username,
- &uid, &gid,
- &sam_account);
- }
+
+ /* try to fill the same account.. If getpwnam() fails, then try the
+ add user script (2.2.x behavior) */
+
+ nt_status = fill_sam_account(mem_ctx, nt_domain, internal_username,
+ &found_username, &uid, &gid, &sam_account);
+
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
+ DEBUG(3,("User %s does not exist, trying to add it\n",
+ internal_username));
+ auth_add_user_script(nt_domain, internal_username);
+ nt_status = fill_sam_account(mem_ctx, nt_domain,
+ internal_username, &found_username,
+ &uid, &gid, &sam_account);
}
if (!NT_STATUS_IS_OK(nt_status)) {
/* Store the user group information in the server_info
returned to the caller. */
- if (!NT_STATUS_IS_OK(nt_status
- = get_user_groups_from_local_sam((*server_info)->unix_name,
- uid, gid,
- &n_lgroupSIDs,
- &lgroupSIDs,
- &unix_groups)))
+ nt_status = get_user_groups_from_local_sam((*server_info)->unix_name,
+ uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups);
+ if ( !NT_STATUS_IS_OK(nt_status) )
{
DEBUG(4,("get_user_groups_from_local_sam failed\n"));
return nt_status;
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- request.data.auth_crap.flags = WINBIND_PAM_INFO3_NDR;
+ request.flags = WBFLAG_PAM_INFO3_NDR;
push_utf8_fstring(request.data.auth_crap.user,
user_info->smb_name.str);
Check to see if we are a DO for this domain
*****************************************************************************/
-#define IS_DC_FOR_DOMAIN(x) ( (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC) \
- && strequal((x), lp_workgroup()) )
+#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC)
#endif /* _SMB_MACROS_H */
}
if (ldap_state->ldap_struct != NULL) {
- DEBUG(5,("smbldap_open: already connected to the LDAP server\n"));
+ DEBUG(11,("smbldap_open: already connected to the LDAP server\n"));
return LDAP_SUCCESS;
}
/* see if we should disable winbindd lookups for local users */
if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) {
- if ( setenv(WINBINDD_DONT_ENV, "1", 1) == -1 )
+ if ( !winbind_off() )
DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n",
WINBINDD_DONT_ENV));
else
#endif
/* allow winbindd lookups */
- setenv( WINBINDD_DONT_ENV, "0", 1);
+ winbind_on();
return retval;
}
return (result == NSS_STATUS_SUCCESS);
}
+/* Call winbindd to convert SID to uid. Do not allocate */
+
+BOOL winbind_sid_to_uid_query(uid_t *puid, const DOM_SID *sid)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
+ fstring sid_str;
+
+ if (!puid)
+ return False;
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ sid_to_string(sid_str, sid);
+ fstrcpy(request.data.sid, sid_str);
+
+ request.flags = WBFLAG_QUERY_ONLY;
+
+ /* Make request */
+
+ result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
+
+ /* Copy out result */
+
+ if (result == NSS_STATUS_SUCCESS) {
+ *puid = response.data.uid;
+ }
+
+ return (result == NSS_STATUS_SUCCESS);
+}
+
/* Call winbindd to convert SID to gid */
BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
return (result == NSS_STATUS_SUCCESS);
}
+/* Call winbindd to convert SID to gid. Do not allocate */
+
+BOOL winbind_sid_to_gid_query(gid_t *pgid, const DOM_SID *sid)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int result;
+ fstring sid_str;
+
+ if (!pgid)
+ return False;
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ sid_to_string(sid_str, sid);
+ fstrcpy(request.data.sid, sid_str);
+
+ request.flags = WBFLAG_QUERY_ONLY;
+
+ /* Make request */
+
+ result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
+
+ /* Copy out result */
+
+ if (result == NSS_STATUS_SUCCESS) {
+ *pgid = response.data.gid;
+ }
+
+ return (result == NSS_STATUS_SUCCESS);
+}
+
/* Call winbindd to convert gid to sid */
BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
return(status);
return winbindd_get_response(response);
}
+
+/*************************************************************************
+ A couple of simple jfunctions to disable winbindd lookups and re-
+ enable them
+ ************************************************************************/
+
+BOOL winbind_off( void )
+{
+ return (setenv( WINBINDD_DONT_ENV, "1", 1 ) != -1);
+}
+
+BOOL winbind_on( void )
+{
+ return (setenv( WINBINDD_DONT_ENV, "0", 1 ) != -1);
+}
+
if (!parse_domain_user(tmp, name_domain, name_group))
return WINBINDD_ERROR;
- /* don't handle our own domain if we are a DC. This code handles cases where
+ /* don't handle our own domain if we are a DC ( or a member of a Samba domain
+ that shares UNIX accounts). This code handles cases where
the account doesn't exist anywhere and gets passed on down the NSS layer */
- if ( IS_DC_FOR_DOMAIN(domain->name) ) {
+ if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
name_domain, name_group));
return WINBINDD_ERROR;
return WINBINDD_ERROR;
}
- if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &gid))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid, 0))) {
DEBUG(1, ("error converting unix gid to sid\n"));
return WINBINDD_ERROR;
}
return WINBINDD_ERROR;
/* Get rid from gid */
- if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, state->request.data.gid))) {
+ if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) {
DEBUG(1, ("could not convert gid %d to rid\n",
state->request.data.gid));
return WINBINDD_ERROR;
struct getent_state *domain_state;
- /* don't add our domaina if we are a PDC */
+ /* don't add our domaina if we are a PDC or if we
+ are a member of a Samba domain */
- if ( IS_DC_FOR_DOMAIN(domain->name) )
+ if ( (IS_DC || lp_winbind_trusted_domains_only())
+ && strequal(domain->name, lp_workgroup()) )
+ {
continue;
+ }
/* Create a state record for this domain */
sid_copy(&group_sid, &domain->sid);
sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
- if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &group_gid))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid, 0))) {
DEBUG(1, ("could not look up gid for group %s\n",
name_list[ent->sam_entry_index].acct_name));
/* Map to a gid */
- if (!NT_STATUS_IS_OK(sid_to_gid(&info3->other_sids[i].sid,
- &gid_list[num_gids])) )
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&info3->other_sids[i].sid, &gid_list[num_gids], 0)) )
{
DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
sid_string_static(&info3->other_sids[i].sid)));
sid_copy( &group_sid, &domain->sid );
sid_append_rid( &group_sid, info3->gids[i].g_rid );
- if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &gid_list[num_gids])) ) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid_list[num_gids], 0)) ) {
DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n",
sid_string_static(&group_sid)));
}
goto done;
for (i = 0; i < num_groups; i++) {
- if (!NT_STATUS_IS_OK(sid_to_gid(user_grpsids[i], &gid_list[num_gids]))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_grpsids[i], &gid_list[num_gids], 0))) {
DEBUG(1, ("unable to convert group sid %s to gid\n",
sid_string_static(user_grpsids[i])));
continue;
WINBINDD_NUM_CMDS
};
-#define WINBIND_PAM_INFO3_NDR 0x0001
-#define WINBIND_PAM_INFO3_TEXT 0x0002
-#define WINBIND_PAM_NTKEY 0x0004
-#define WINBIND_PAM_LMKEY 0x0008
-#define WINBIND_PAM_CONTACT_TRUSTDOM 0x0010
+#define WBFLAG_PAM_INFO3_NDR 0x0001
+#define WBFLAG_PAM_INFO3_TEXT 0x0002
+#define WBFLAG_PAM_NTKEY 0x0004
+#define WBFLAG_PAM_LMKEY 0x0008
+#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010
+#define WBFLAG_QUERY_ONLY 0x0020
/* Winbind request structure */
uint32 length;
enum winbindd_cmd cmd; /* Winbindd command to execute */
pid_t pid; /* pid of calling process */
+ uint32 flags; /* flags relavant to a given request */
union {
fstring winsreq; /* WINS request */
fstring nt_resp;
uint16 nt_resp_len;
fstring workstation;
- uint32 flags;
} auth_crap;
struct {
fstring user;
DOM_SID sid;
char *pwd;
- if ( lp_server_role()==ROLE_DOMAIN_MEMBER || strequal(domain, lp_workgroup()) )
+ /* if we are a DC and this is not our domain, then lookup an account
+ for the domain trust */
+
+ if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() )
{
- /*
- * Get the machine account password for the domain to contact.
- * This is either our own domain for a workstation, or possibly
- * any domain for a PDC with trusted domains.
- */
-
- if ( !secrets_fetch_trust_account_password (domain, ret_pwd,
- pass_last_set_time, channel) )
+ if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
+ pass_last_set_time) )
{
DEBUG(0, ("get_trust_pw: could not fetch trust account "
- "password for my domain %s\n", domain));
+ "password for trusted domain %s\n", domain));
return False;
}
+ *channel = SEC_CHAN_DOMAIN;
+ E_md4hash(pwd, ret_pwd);
+ SAFE_FREE(pwd);
+
return True;
}
- else if ( lp_allow_trusted_domains() )
+ else /* just get the account for our domain (covers
+ ROLE_DOMAIN_MEMBER as well */
{
- /* if we are not a domain member, then we must be a DC and
- this must be a trusted domain */
+ /* get the machine trust account for our domain */
- if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
- pass_last_set_time) )
+ if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd,
+ pass_last_set_time, channel) )
{
DEBUG(0, ("get_trust_pw: could not fetch trust account "
- "password for trusted domain %s\n", domain));
+ "password for my domain %s\n", domain));
return False;
}
- *channel = SEC_CHAN_DOMAIN;
- E_md4hash(pwd, ret_pwd);
- SAFE_FREE(pwd);
-
return True;
}
int attempts = 0;
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
+ const char *contact_domain;
/* Ensure null termination */
state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
goto done;
}
+ /* what domain should we contact? */
+
+ if ( IS_DC )
+ contact_domain = name_domain;
+ else
+ contact_domain = lp_workgroup();
+
/* check authentication loop */
do {
ZERO_STRUCT(ret_creds);
/* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(name_domain, trust_passwd,
+ result = cm_get_netlogon_cli(contact_domain, trust_passwd,
sec_channel_type, False, &cli);
if (!NT_STATUS_IS_OK(result)) {
char *user = NULL;
const char *domain = NULL;
const char *workstation;
+ const char *contact_domain;
DOM_CRED ret_creds;
int attempts = 0;
lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len);
nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
+ /* what domain should we contact? */
+
+ if ( IS_DC )
+ contact_domain = domain;
+ else
+ contact_domain = lp_workgroup();
+
do {
ZERO_STRUCT(info3);
ZERO_STRUCT(ret_creds);
/* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(domain, trust_passwd, sec_channel_type, False, &cli);
+ result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, False, &cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
netsamlogon_cache_store( cli->mem_ctx, &info3 );
wcache_invalidate_samlogon(find_domain_from_name(domain), &info3);
- if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) {
+ if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
result = append_info3_as_ndr(mem_ctx, state, &info3);
}
- if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
+ if (state->request.flags & WBFLAG_PAM_NTKEY) {
memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
}
- if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) {
+ if (state->request.flags & WBFLAG_PAM_LMKEY) {
memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */);
}
}
DEBUG(3,("pdb: sid_to_name sid=%s\n", sid_string_static(sid)));
- if (NT_STATUS_IS_OK(sid_to_uid(sid, &id))) { /* this is a user */
+ if (NT_STATUS_IS_OK(idmap_sid_to_uid(sid, &id, 0))) { /* this is a user */
if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
return result;
*type = SID_NAME_USER;
result = NT_STATUS_OK;
- } else if (NT_STATUS_IS_OK(sid_to_gid(sid, &id))) { /* this is a group */
+ } else if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &id, 0))) { /* this is a group */
DEBUG(3,("pdb: sid_to_name: group support not implemented\n"));
result = NT_STATUS_UNSUCCESSFUL;
enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
+ uint32 flags = 0x0;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
/* Split sid into domain sid and user rid */
if (!string_to_sid(&sid, state->request.data.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request.data.sid));
+ DEBUG(1, ("Could not get convert sid %s from string\n", state->request.data.sid));
return WINBINDD_ERROR;
}
-
+
+ if ( state->request.flags & WBFLAG_QUERY_ONLY )
+ flags = ID_QUERY_ONLY;
+
/* Find uid for this sid and return it */
- if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &(state->response.data.uid)))) {
- DEBUG(1, ("Could not get uid for sid %s\n",
- state->request.data.sid));
+ if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) {
+ DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
return WINBINDD_ERROR;
}
enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
+ uint32 flags = 0x0;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
state->request.data.sid));
if (!string_to_sid(&sid, state->request.data.sid)) {
- DEBUG(1, ("Could not cvt string to sid %s\n",
- state->request.data.sid));
+ DEBUG(1, ("Could not cvt string to sid %s\n", state->request.data.sid));
return WINBINDD_ERROR;
}
+ if ( state->request.flags & WBFLAG_QUERY_ONLY )
+ flags = ID_QUERY_ONLY;
+
/* Find gid for this sid and return it */
- if (!NT_STATUS_IS_OK(sid_to_gid(&sid, &(state->response.data.gid)))) {
- DEBUG(1, ("Could not get gid for sid %s\n",
- state->request.data.sid));
+ if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) {
+ DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
return WINBINDD_ERROR;
}
state->request.data.uid));
/* Lookup rid for this uid */
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, state->request.data.uid))) {
+ if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&sid, state->request.data.uid))) {
DEBUG(1, ("Could not convert uid %d to rid\n",
state->request.data.uid));
return WINBINDD_ERROR;
state->request.data.gid));
/* Lookup sid for this uid */
- if (!NT_STATUS_IS_OK(gid_to_sid(&sid, state->request.data.gid))) {
+ if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&sid, state->request.data.gid))) {
DEBUG(1, ("Could not convert gid %d to sid\n",
state->request.data.gid));
return WINBINDD_ERROR;
/* Resolve the uid number */
- if (!NT_STATUS_IS_OK(sid_to_uid(user_sid, &(pw->pw_uid)))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &(pw->pw_uid), 0))) {
DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid)));
return False;
}
/* Resolve the gid number */
- if (!NT_STATUS_IS_OK(sid_to_gid(group_sid, &(pw->pw_gid)))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &(pw->pw_gid), 0))) {
DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid)));
return False;
}
name_user))
return WINBINDD_ERROR;
- /* don't handle our own domain if we are a DC. This code handles cases where
+ /* don't handle our own domain if we are a DC ( or a member of a Samba domain
+ that shares UNIX accounts). This code handles cases where
the account doesn't exist anywhere and gets passed on down the NSS layer */
- if ( IS_DC_FOR_DOMAIN(domain->name) ) {
+ if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
DEBUG(7,("winbindd_getpwnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
name_domain, name_user));
return WINBINDD_ERROR;
/* Get rid from uid */
- if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, state->request.data.uid))) {
+ if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&user_sid, state->request.data.uid))) {
DEBUG(1, ("could not convert uid %d to SID\n",
state->request.data.uid));
return WINBINDD_ERROR;
/* Check group has a gid number */
- if (!NT_STATUS_IS_OK(sid_to_gid(user_info.group_sid, &gid))) {
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_info.group_sid, &gid, 0))) {
DEBUG(1, ("error getting group id for user %s\n", user_name));
talloc_destroy(mem_ctx);
return WINBINDD_ERROR;
struct getent_state *domain_state;
- /* don't add our domaina if we are a PDC */
+ /* don't add our domaina if we are a PDC or if we
+ are a member of a Samba domain */
- if ( IS_DC_FOR_DOMAIN( domain->name ) )
- continue;
+ if ( (IS_DC || lp_winbind_trusted_domains_only())
+ && strequal(domain->name, lp_workgroup()) )
+ {
+ continue;
+ }
/* Create a state record for this domain */
char *szSourceEnv;
char *szIdmapUID;
char *szIdmapGID;
- BOOL *bIdmapOnly;
- char *szNonUnixAccountRange;
+ BOOL bEnableRidAlgorithm;
int AlgorithmicRidBase;
char *szTemplateHomedir;
char *szTemplateShell;
BOOL bWinbindEnumUsers;
BOOL bWinbindEnumGroups;
BOOL bWinbindUseDefaultDomain;
+ BOOL bWinbindTrustedDomainsOnly;
char *szWinbindBackend;
char *szIdmapBackend;
char *szAddShareCommand;
{"Winbind options", P_SEP, P_SEPARATOR},
- {"idmap only", P_BOOL, P_GLOBAL, &Globals.bIdmapOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+ {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEPRECATED},
{"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEPRECATED },
{"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+ {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
};
string_set(&Globals.szWinbindSeparator, "\\");
string_set(&Globals.szAclCompat, "");
- Globals.winbind_cache_time = 600; /* 5 minutes */
+ Globals.winbind_cache_time = 300; /* 5 minutes */
Globals.bWinbindEnumUsers = True;
Globals.bWinbindEnumGroups = True;
Globals.bWinbindUseDefaultDomain = False;
+ Globals.bWinbindTrustedDomainsOnly = False;
- Globals.bIdmapOnly = False;
+ Globals.bEnableRidAlgorithm = True;
Globals.name_cache_timeout = 660; /* In seconds */
FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
+FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
-FN_GLOBAL_BOOL(lp_idmap_only, &Globals.bIdmapOnly)
+FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
#ifdef WITH_LDAP_SAMCONFIG
FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
/*************************************************************
Change a password entry in the local smbpasswd file.
-
-It is currently being called by SWAT and by smbpasswd.
-
- --jerry
*************************************************************/
BOOL local_password_change(const char *user_name, int local_flags,
pdb_free_sam(&sam_pass);
return True;
}
+
+/****************************************************************************
+ Convert a uid to SID - locally.
+****************************************************************************/
+
+DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
+{
+ SAM_ACCOUNT *sampw = NULL;
+ struct passwd *unix_pw;
+
+
+
+ winbind_off();
+ unix_pw = sys_getpwuid( uid );
+ winbind_on();
+
+ if ( !unix_pw ) {
+ DEBUG(4,("local_uid_to_sid: host has know idea of uid %d\n", uid));
+ return NULL;
+ }
+
+ if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
+ DEBUG(0,("local_uid_to_sid: failed to allocate SAM_ACCOUTN object\n"));
+ return NULL;
+ }
+
+ if ( !pdb_getsampwnam( sampw, unix_pw->pw_name ) ) {
+ DEBUG(4,("local_uid_to_sid: User %s [uid == %d] has no samba account\n",
+ unix_pw->pw_name, uid));
+ return NULL;
+ }
+
+ sid_copy( psid, pdb_get_user_sid(sampw) );
+
+ DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n",
+ (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
+
+ return psid;
+}
+
+/****************************************************************************
+ Convert a SID to uid - locally.
+****************************************************************************/
+
+BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+ SAM_ACCOUNT *sampw = NULL;
+ struct passwd *unix_pw;
+ const char *user_name;
+
+ *name_type = SID_NAME_UNKNOWN;
+
+ sid_copy(&dom_sid, psid);
+ sid_split_rid(&dom_sid, &rid);
+
+ /*
+ * We can only convert to a uid if this is our local
+ * Domain SID (ie. we are the controling authority).
+ */
+ if ( !sid_equal(get_global_sam_sid(), &dom_sid) )
+ return False;
+
+
+ /* lookup the user account */
+
+ if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
+ DEBUG(0,("local_sid_to_uid: Failed to allocate memory for SAM_ACCOUNT object\n"));
+ return False;
+ }
+
+ if ( !pdb_getsampwsid(sampw, psid) ) {
+ DEBUG(8,("local_sid_to_uid: Could not find SID %s in passdb\n",
+ sid_string_static(psid)));
+ return False;
+ }
+
+ user_name = pdb_get_username(sampw);
+
+ winbind_off();
+ unix_pw = sys_getpwnam( user_name );
+ winbind_on();
+
+ if ( !unix_pw ) {
+ DEBUG(0,("local_sid_to_uid: %s found in passdb but getpwnam() return NULL!\n",
+ user_name));
+ pdb_free_sam( &sampw );
+ return False;
+ }
+
+ *puid = unix_pw->pw_uid;
+
+ DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_string_static(psid),
+ (unsigned int)*puid, user_name ));
+
+ *name_type = SID_NAME_USER;
+
+ return True;
+}
+
+/****************************************************************************
+ Convert a gid to SID - locally.
+****************************************************************************/
+
+DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
+{
+ GROUP_MAP group;
+
+ /* we don't need to disable winbindd since the gid is stored in
+ the GROUP_MAP object */
+
+ if ( !pdb_getgrgid( &group, gid ) ) {
+
+ /* fallback to rid mapping if enabled */
+
+ if ( lp_enable_rid_algorithm() ) {
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, pdb_gid_to_group_rid(gid));
+
+ DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n",
+ (unsigned int)gid, sid_string_static(psid)));
+
+ return psid;
+ }
+ else
+ return NULL;
+ }
+
+ sid_copy( psid, &group.sid );
+
+ DEBUG(10,("local_gid_to_sid: gid (%d) -> SID %s.\n",
+ (unsigned int)gid, sid_string_static(psid)));
+
+ return psid;
+}
+
+/****************************************************************************
+ Convert a SID to gid - locally.
+****************************************************************************/
+
+BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+ GROUP_MAP group;
+
+ *name_type = SID_NAME_UNKNOWN;
+
+ /* This call can enumerate grou mappings for foreign sids as well.
+ So don't check for a match against our domain SID */
+
+ /* we don't need to disable winbindd since the gid is stored in
+ the GROUP_MAP object */
+
+ if ( !pdb_getgrsid(&group, *psid) ) {
+
+ /* fallback to rid mapping if enabled */
+
+ if ( lp_enable_rid_algorithm() ) {
+ sid_copy(&dom_sid, psid);
+ sid_split_rid(&dom_sid, &rid);
+
+ if (!sid_equal(get_global_sam_sid(), &dom_sid) ) {
+ DEBUG(5,("local_sid_to_gid: RID algorithm only supported for our domain (not %s)\n",
+ sid_string_static(&dom_sid)));
+ return False;
+ }
+
+ if (!sid_peek_rid(psid, &rid)) {
+ DEBUG(10,("local_sid_to_uid: invalid SID!\n"));
+ return False;
+ }
+
+ DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n"));
+
+ if (fallback_pdb_rid_is_user(rid)) {
+ DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid)));
+ return False;
+ } else {
+ *pgid = pdb_group_rid_to_gid(rid);
+ DEBUG(10,("local_sid_to_gid: mapping: %s -> %u\n", sid_string_static(psid), (unsigned int)(*pgid)));
+ return True;
+ }
+ }
+
+ return False;
+ }
+
+ *pgid = group.gid;
+
+ DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
+ (unsigned int)*pgid));
+
+ return True;
+}
+
+
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if (count < 1) {
- DEBUG(4, ("Did not find group for filter %s\n", filter));
+ DEBUG(4, ("Did not find group\n"));
return NT_STATUS_NO_SUCH_GROUP;
}
(struct ldapsam_privates *)methods->private_data;
LDAPMessage *result = NULL;
LDAPMod **mods = NULL;
+ int count;
char *tmp;
pstring dn;
return NT_STATUS_UNSUCCESSFUL;
}
- if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 1) {
+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+
+ if ( count == 0 )
+ return NT_STATUS_UNSUCCESSFUL;
+
+ if (count > 1) {
DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
map->gid));
ldap_msgfree(result);
{
uint32 id_low, id_high;
- if (lp_idmap_only()) {
+ if (!lp_enable_rid_algorithm()) {
*low = BASE_RID;
*high = (uint32)-1;
}
}
/*****************************************************************
- *THE CANONICAL* convert uid_t to SID function.
check idmap if uid is in idmap range, otherwise falls back to
- the legacy algorithmic mapping.
- Returns SID pointer.
+ the legacy algorithmic mapping. Returns SID pointer.
*****************************************************************/
-NTSTATUS uid_to_sid(DOM_SID *sid, uid_t uid)
+NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
unid_t id;
int flags;
- DEBUG(10,("uid_to_sid: uid = [%d]\n", uid));
+ DEBUG(10,("idmap_uid_to_sid: uid = [%d]\n", uid));
flags = ID_USERID;
- if (!lp_idmap_only() && !idmap_check_ugid_is_in_free_range(uid)) {
- flags |= ID_QUERY_ONLY;
- }
-
id.uid = uid;
- if (!NT_STATUS_IS_OK(ret = idmap_get_sid_from_id(sid, id, flags))) {
- DEBUG(10, ("uid_to_sid: Failed to map uid = [%u]\n", (unsigned int)uid));
- if (flags & ID_QUERY_ONLY) {
- sid_copy(sid, get_global_sam_sid());
- sid_append_rid(sid, fallback_pdb_uid_to_user_rid(uid));
-
- DEBUG(10,("uid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", (unsigned int)uid, sid_string_static(sid)));
- ret = NT_STATUS_OK;
- }
- }
-
- return ret;
+
+ return idmap_get_sid_from_id(sid, id, flags);
}
/*****************************************************************
- *THE CANONICAL* convert gid_t to SID function.
check idmap if gid is in idmap range, otherwise falls back to
the legacy algorithmic mapping.
Group mapping is used for gids that maps to Wellknown SIDs
Returns SID pointer.
*****************************************************************/
-NTSTATUS gid_to_sid(DOM_SID *sid, gid_t gid)
+NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
unid_t id;
int flags;
- DEBUG(10,("gid_to_sid: gid = [%d]\n", gid));
+ DEBUG(10,("idmap_gid_to_sid: gid = [%d]\n", gid));
flags = ID_GROUPID;
- if (!lp_idmap_only() && !idmap_check_ugid_is_in_free_range(gid)) {
+ if (!idmap_check_ugid_is_in_free_range(gid)) {
flags |= ID_QUERY_ONLY;
}
id.gid = gid;
- if (!NT_STATUS_IS_OK(ret = idmap_get_sid_from_id(sid, id, flags))) {
- DEBUG(10, ("gid_to_sid: Failed to map gid = [%u]\n", (unsigned int)gid));
- if (flags & ID_QUERY_ONLY) {
- sid_copy(sid, get_global_sam_sid());
- sid_append_rid(sid, pdb_gid_to_group_rid(gid));
-
- DEBUG(10,("gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", (unsigned int)gid, sid_string_static(sid)));
- ret = NT_STATUS_OK;
- }
- }
-
- return ret;
+ return idmap_get_sid_from_id(sid, id, flags);
}
/*****************************************************************
- *THE CANONICAL* convert SID to uid function.
if it is a foreign sid or it is in idmap rid range check idmap,
otherwise falls back to the legacy algorithmic mapping.
Returns True if this name is a user sid and the conversion
was done correctly, False if not.
*****************************************************************/
-NTSTATUS sid_to_uid(const DOM_SID *sid, uid_t *uid)
+NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- BOOL fallback = False;
unid_t id;
- int flags;
-
- DEBUG(10,("sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
-
- flags = ID_USERID;
- if (!lp_idmap_only()) {
- if (!idmap_check_sid_is_in_free_range(sid)) {
- flags |= ID_QUERY_ONLY;
- fallback = True;
- }
- }
- if (NT_STATUS_IS_OK(ret = idmap_get_id_from_sid(&id, &flags, sid))) {
+ DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
- DEBUG(10,("sid_to_uid: uid = [%d]\n", id.uid));
+ flags |= ID_USERID;
+ ret = idmap_get_id_from_sid(&id, &flags, sid);
+
+ if ( NT_STATUS_IS_OK(ret) ) {
+ DEBUG(10,("idmap_sid_to_uid: uid = [%d]\n", id.uid));
*uid = id.uid;
-
- } else if (fallback) {
- uint32 rid;
-
- if (!sid_peek_rid(sid, &rid)) {
- DEBUG(10,("sid_to_uid: invalid SID!\n"));
- ret = NT_STATUS_INVALID_PARAMETER;
- goto done;
- }
-
- DEBUG(10,("sid_to_uid: Fall back to algorithmic mapping\n"));
+ }
- if (!fallback_pdb_rid_is_user(rid)) {
- DEBUG(3, ("sid_to_uid: SID %s is *NOT* a user\n", sid_string_static(sid)));
- ret = NT_STATUS_UNSUCCESSFUL;
- } else {
- *uid = fallback_pdb_user_rid_to_uid(rid);
- DEBUG(10,("sid_to_uid: mapping: %s -> %u\n", sid_string_static(sid), (unsigned int)(*uid)));
- ret = NT_STATUS_OK;
- }
- }
-
-done:
return ret;
+
}
/*****************************************************************
was done correctly, False if not.
*****************************************************************/
-NTSTATUS sid_to_gid(const DOM_SID *sid, gid_t *gid)
+NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- BOOL fallback = False;
unid_t id;
- int flags;
DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
- flags = ID_GROUPID;
- if (!lp_idmap_only()) {
- if (!idmap_check_sid_is_in_free_range(sid)) {
- flags |= ID_QUERY_ONLY;
- fallback = True;
- }
- }
+ flags |= ID_GROUPID;
- if (NT_STATUS_IS_OK(ret = idmap_get_id_from_sid(&id, &flags, sid))) {
-
- DEBUG(10,("sid_to_gid: gid = [%d]\n", id.gid));
+ ret = idmap_get_id_from_sid(&id, &flags, sid);
+
+ if ( NT_STATUS_IS_OK(ret) )
+ {
+ DEBUG(10,("idmap_sid_to_gid: gid = [%d]\n", id.gid));
*gid = id.gid;
-
- } else if (fallback) {
- uint32 rid;
-
- if (!sid_peek_rid(sid, &rid)) {
- DEBUG(10,("sid_to_uid: invalid SID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG(10,("sid_to_gid: Fall back to algorithmic mapping\n"));
-
- if (fallback_pdb_rid_is_user(rid)) {
- DEBUG(3, ("sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(sid)));
- ret = NT_STATUS_UNSUCCESSFUL;
- } else {
- *gid = pdb_group_rid_to_gid(rid);
- DEBUG(10,("sid_to_gid: mapping: %s -> %u\n", sid_string_static(sid), (unsigned int)(*gid)));
- ret = NT_STATUS_OK;
- }
}
return ret;
}
+
/***************************************************************************
Check first, call set_mapping if it doesn't already exist.
***************************************************************************/
if (!init_registry())
exit(1);
- /* Initialise the password backed before idmap and the global_sam_sid
+ /* Initialise the password backed before the global_sam_sid
to ensure that we fetch from ldap before we make a domain sid up */
if(!initialize_password_db(False))
static_init_auth;
- {
- const char *idmap_back = lp_idmap_backend();
-
- if (!idmap_init((idmap_back && *idmap_back) ? "winbind" : NULL))
- exit(1);
- }
-
- if (!idmap_init_wellknown_sids()) {
- DEBUG(0,("ERROR: Samba failed to initialize it's 'well known' SID -> ID mapping tables.\n"));
- exit(1);
- }
-
static_init_rpc;
init_modules();
}
return True;
}
+
+
+/*****************************************************************
+ Id mapping cache. This is to avoid Winbind mappings already
+ seen by smbd to be queried too frequently, keeping winbindd
+ busy, and blocking smbd while winbindd is busy with other
+ stuff. Written by Michael Steffens <michael.steffens@hp.com>,
+ modified to use linked lists by jra.
+*****************************************************************/
+
+#define MAX_UID_SID_CACHE_SIZE 100
+#define TURNOVER_UID_SID_CACHE_SIZE 10
+#define MAX_GID_SID_CACHE_SIZE 100
+#define TURNOVER_GID_SID_CACHE_SIZE 10
+
+static size_t n_uid_sid_cache = 0;
+static size_t n_gid_sid_cache = 0;
+
+static struct uid_sid_cache {
+ struct uid_sid_cache *next, *prev;
+ uid_t uid;
+ DOM_SID sid;
+ enum SID_NAME_USE sidtype;
+} *uid_sid_cache_head;
+
+static struct gid_sid_cache {
+ struct gid_sid_cache *next, *prev;
+ gid_t gid;
+ DOM_SID sid;
+ enum SID_NAME_USE sidtype;
+} *gid_sid_cache_head;
+
+/*****************************************************************
+ Find a SID given a uid.
+*****************************************************************/
+
+static BOOL fetch_sid_from_uid_cache(const DOM_SID *psid, uid_t uid)
+{
+ struct uid_sid_cache *pc;
+
+ for (pc = uid_sid_cache_head; pc; pc = pc->next) {
+ if (pc->uid == uid) {
+ fstring sid;
+ *psid = pc->sid;
+ DEBUG(3,("fetch sid from uid cache %u -> %s\n",
+ (unsigned int)uid, sid_to_string(sid, psid)));
+ DLIST_PROMOTE(uid_sid_cache_head, pc);
+ return True;
+ }
+ }
+ return False;
+}
+
+/*****************************************************************
+ Find a uid given a SID.
+*****************************************************************/
+
+static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
+{
+ struct uid_sid_cache *pc;
+
+ for (pc = uid_sid_cache_head; pc; pc = pc->next) {
+ if (sid_compare(&pc->sid, psid) == 0) {
+ fstring sid;
+ *puid = pc->uid;
+ DEBUG(3,("fetch uid from cache %u -> %s\n",
+ (unsigned int)*puid, sid_to_string(sid, psid)));
+ DLIST_PROMOTE(uid_sid_cache_head, pc);
+ return True;
+ }
+ }
+ return False;
+}
+
+/*****************************************************************
+ Store uid to SID mapping in cache.
+*****************************************************************/
+
+static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
+{
+ struct uid_sid_cache *pc;
+
+ if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
+ /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
+ struct uid_sid_cache *pc_next;
+ size_t i;
+
+ for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
+ ;
+ for(; pc; pc = pc_next) {
+ pc_next = pc->next;
+ DLIST_REMOVE(uid_sid_cache_head,pc);
+ SAFE_FREE(pc);
+ n_uid_sid_cache--;
+ }
+ }
+
+ pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache));
+ if (!pc)
+ return;
+ pc->uid = uid;
+ sid_copy(&pc->sid, psid);
+ DLIST_ADD(uid_sid_cache_head, pc);
+ n_uid_sid_cache++;
+}
+
+/*****************************************************************
+ Find a SID given a gid.
+*****************************************************************/
+
+static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
+{
+ struct gid_sid_cache *pc;
+
+ for (pc = gid_sid_cache_head; pc; pc = pc->next) {
+ if (pc->gid == gid) {
+ fstring sid;
+ *psid = pc->sid;
+ DEBUG(3,("fetch sid from gid cache %u -> %s\n",
+ (unsigned int)gid, sid_to_string(sid, psid)));
+ DLIST_PROMOTE(gid_sid_cache_head, pc);
+ return True;
+ }
+ }
+ return False;
+}
+
+/*****************************************************************
+ Find a gid given a SID.
+*****************************************************************/
+
+static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
+{
+ struct gid_sid_cache *pc;
+
+ for (pc = gid_sid_cache_head; pc; pc = pc->next) {
+ if (sid_compare(&pc->sid, psid) == 0) {
+ fstring sid;
+ *pgid = pc->gid;
+ DEBUG(3,("fetch uid from cache %u -> %s\n",
+ (unsigned int)*pgid, sid_to_string(sid, psid)));
+ DLIST_PROMOTE(gid_sid_cache_head, pc);
+ return True;
+ }
+ }
+ return False;
+}
+
+/*****************************************************************
+ Store gid to SID mapping in cache.
+*****************************************************************/
+
+static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
+{
+ struct gid_sid_cache *pc;
+
+ if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
+ /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
+ struct gid_sid_cache *pc_next;
+ size_t i;
+
+ for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
+ ;
+ for(; pc; pc = pc_next) {
+ pc_next = pc->next;
+ DLIST_REMOVE(gid_sid_cache_head,pc);
+ SAFE_FREE(pc);
+ n_gid_sid_cache--;
+ }
+ }
+
+ pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache));
+ if (!pc)
+ return;
+ pc->gid = gid;
+ sid_copy(&pc->sid, psid);
+ DLIST_ADD(gid_sid_cache_head, pc);
+ n_gid_sid_cache++;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert uid_t to SID function.
+ check idmap if uid is in idmap range, otherwise falls back to
+ the legacy algorithmic mapping.
+ A special cache is used for uids that maps to Wellknown SIDs
+ Returns SID pointer.
+*****************************************************************/
+
+NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
+{
+ uid_t low, high;
+ fstring sid;
+
+ if (fetch_sid_from_uid_cache(psid, uid))
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+
+ if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) {
+ if (winbind_uid_to_sid(psid, uid)) {
+
+ DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)uid, sid_to_string(sid, psid)));
+
+ if (psid)
+ store_uid_sid_cache(psid, uid);
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+ }
+ }
+
+ local_uid_to_sid(psid, uid);
+
+ DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid)));
+
+ if (psid)
+ store_uid_sid_cache(psid, uid);
+
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert gid_t to SID function.
+ check idmap if gid is in idmap range, otherwise falls back to
+ the legacy algorithmic mapping.
+ Group mapping is used for gids that maps to Wellknown SIDs
+ Returns SID pointer.
+*****************************************************************/
+
+NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
+{
+ gid_t low, high;
+ fstring sid;
+
+ if (fetch_sid_from_gid_cache(psid, gid))
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+
+ if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) {
+ if (winbind_gid_to_sid(psid, gid)) {
+
+ DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)gid, sid_to_string(sid, psid)));
+
+ if (psid)
+ store_gid_sid_cache(psid, gid);
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+ }
+ }
+
+ local_gid_to_sid(psid, gid);
+
+ DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
+
+ if (psid)
+ store_gid_sid_cache(psid, gid);
+
+ return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert SID to uid function.
+ if it is a foreign sid or it is in idmap rid range check idmap,
+ otherwise falls back to the legacy algorithmic mapping.
+ A special cache is used for uids that maps to Wellknown SIDs
+ Returns True if this name is a user sid and the conversion
+ was done correctly, False if not.
+*****************************************************************/
+
+NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
+{
+ fstring dom_name, name, sid_str;
+ enum SID_NAME_USE name_type;
+ BOOL ret;
+
+ if (fetch_uid_from_cache(puid, psid))
+ return NT_STATUS_OK;
+
+ /*
+ * First we must look up the name and decide if this is a user sid.
+ */
+
+ if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) {
+ DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n",
+ sid_to_string(sid_str, psid) ));
+
+ ret = local_sid_to_uid(puid, psid, &name_type);
+ if (ret)
+ store_uid_sid_cache(psid, *puid);
+ return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
+ }
+
+ /*
+ * Ensure this is a user sid.
+ */
+
+ if (name_type != SID_NAME_USER) {
+ DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n",
+ (unsigned int)name_type ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* query only first */
+
+ if ( !winbind_sid_to_uid_query(puid, psid) )
+ {
+ DEBUG(10,("sid_to_uid: winbind query for sid %s failed.\n",
+ sid_to_string(sid_str, psid) ));
+
+ /* see if we have a local mapping */
+
+ if ( local_sid_to_uid(puid, psid, &name_type) ) {
+ store_uid_sid_cache(psid, *puid);
+ return NT_STATUS_OK;
+ }
+
+ /* Call back to winbind to allocate a new uid */
+
+ if ( !winbind_sid_to_uid(puid, psid) ) {
+ DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
+ sid_to_string(sid_str, psid) ));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid),
+ (unsigned int)*puid ));
+
+ store_uid_sid_cache(psid, *puid);
+
+ return NT_STATUS_OK;
+}
+/*****************************************************************
+ *THE CANONICAL* convert SID to gid function.
+ if it is a foreign sid or it is in idmap rid range check idmap,
+ otherwise falls back to the legacy algorithmic mapping.
+ Group mapping is used for gids that maps to Wellknown SIDs
+ Returns True if this name is a user sid and the conversion
+ was done correctly, False if not.
+*****************************************************************/
+
+NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+{
+ fstring dom_name, name, sid_str;
+ enum SID_NAME_USE name_type;
+ BOOL ret;
+
+ if (fetch_gid_from_cache(pgid, psid))
+ return NT_STATUS_OK;
+
+ /*
+ * First we must look up the name and decide if this is a group sid.
+ */
+
+ if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
+ DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
+ sid_to_string(sid_str, psid) ));
+
+ ret = local_sid_to_gid(pgid, psid, &name_type);
+ if (ret)
+ store_gid_sid_cache(psid, *pgid);
+
+ return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
+ }
+
+ /*
+ * Ensure this is a group sid.
+ */
+
+ if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
+ DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
+ (unsigned int)name_type ));
+
+ ret = local_sid_to_gid(pgid, psid, &name_type);
+ if (ret)
+ store_gid_sid_cache(psid, *pgid);
+ return (ret ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER);
+ }
+
+ /* query only first */
+
+ if ( !winbind_sid_to_gid_query(pgid, psid) )
+ {
+ DEBUG(10,("sid_to_gid: winbind query for sid %s failed.\n",
+ sid_to_string(sid_str, psid) ));
+
+ /* see if we have a local mapping */
+
+ if ( local_sid_to_gid(pgid, psid, &name_type) ) {
+ store_gid_sid_cache(psid, *pgid);
+ return NT_STATUS_OK;
+ }
+
+ /* Call back to winbind to allocate a new uid */
+
+ if ( !winbind_sid_to_gid(pgid, psid) ) {
+ DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n",
+ sid_to_string(sid_str, psid) ));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ else
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid),
+ (unsigned int)*pgid ));
+
+ store_gid_sid_cache(psid, *pgid);
+
+ return NT_STATUS_OK;
+}
+
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- request.data.auth_crap.flags = flags;
+ request.flags = flags;
fstrcpy(request.data.auth_crap.user, username);
return nt_status;
}
- if ((flags & WINBIND_PAM_LMKEY) && lm_key
+ if ((flags & WBFLAG_PAM_LMKEY) && lm_key
&& (memcmp(zeros, response.data.auth.first_8_lm_hash,
sizeof(response.data.auth.first_8_lm_hash)) != 0)) {
memcpy(lm_key, response.data.auth.first_8_lm_hash,
sizeof(response.data.auth.first_8_lm_hash));
}
- if ((flags & WINBIND_PAM_NTKEY) && nt_key
+ if ((flags & WBFLAG_PAM_NTKEY) && nt_key
&& (memcmp(zeros, response.data.auth.nt_session_key,
sizeof(response.data.auth.nt_session_key)) != 0)) {
memcpy(nt_key, response.data.auth.nt_session_key,
x_setbuf(x_stdout, NULL);
if (request_lm_key)
- flags |= WINBIND_PAM_LMKEY;
+ flags |= WBFLAG_PAM_LMKEY;
if (request_nt_key)
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_NTKEY;
nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
opt_workstation,
ZERO_STRUCT(lm_key);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBencrypt(opt_password, chall.data, lm_response.data);
E_deshash(opt_password, lm_hash);
ZERO_STRUCT(lm_key);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBencrypt(opt_password,chall.data,lm_response.data);
E_deshash(opt_password, lm_hash);
ZERO_STRUCT(lm_key);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBNTencrypt(opt_password,chall.data,nt_response.data);
E_md4hash(opt_password, nt_hash);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBNTencrypt(opt_password,chall.data,nt_response.data);
ZERO_STRUCT(lm_key);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBNTencrypt(opt_password,chall.data,nt_response.data);
E_md4hash(opt_password, nt_hash);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_NTKEY;
if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall,
&names_blob,
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_NTKEY;
if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall,
&names_blob,
ZERO_STRUCT(lm_key);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_LMKEY;
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_LMKEY;
+ flags |= WBFLAG_PAM_NTKEY;
SMBencrypt(opt_password,chall.data,lm_response.data);
E_deshash(opt_password, lm_hash);
ZERO_STRUCT(nt_key);
- flags |= WINBIND_PAM_NTKEY;
+ flags |= WBFLAG_PAM_NTKEY;
if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall,
&names_blob,
char nt_passwd[33];
uid = -1;
- sid_to_uid(pdb_get_user_sid(sam_pwent), &uid);
+ idmap_sid_to_uid(pdb_get_user_sid(sam_pwent), &uid, 0);
pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
(uint32)pdb_get_pass_last_set_time(sam_pwent));
} else {
uid = -1;
- sid_to_uid(pdb_get_user_sid(sam_pwent), &uid);
+ idmap_sid_to_uid(pdb_get_user_sid(sam_pwent), &uid, 0);
printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), uid, pdb_get_fullname(sam_pwent));
}