summaryrefslogtreecommitdiff
path: root/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'nsswitch')
-rw-r--r--nsswitch/libwbclient/wbc_sid.c139
-rw-r--r--nsswitch/libwbclient/wbclient.h10
-rw-r--r--nsswitch/wbinfo.c67
-rw-r--r--nsswitch/winbind_struct_protocol.h3
4 files changed, 219 insertions, 0 deletions
diff --git a/nsswitch/libwbclient/wbc_sid.c b/nsswitch/libwbclient/wbc_sid.c
index e2157b9609..46c59a9513 100644
--- a/nsswitch/libwbclient/wbc_sid.c
+++ b/nsswitch/libwbclient/wbc_sid.c
@@ -491,6 +491,145 @@ wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
return wbc_status;
}
+static inline
+wbcErr _sid_to_rid(struct wbcDomainSid *sid, uint32_t *rid)
+{
+ if (sid->num_auths < 1) {
+ return WBC_ERR_INVALID_RESPONSE;
+ }
+ *rid = sid->sub_auths[sid->num_auths - 1];
+
+ return WBC_ERR_SUCCESS;
+}
+
+/* Get alias membership for sids */
+wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
+ struct wbcDomainSid *sids,
+ uint32_t num_sids,
+ uint32_t **alias_rids,
+ uint32_t *num_alias_rids)
+{
+ uint32_t i;
+ const char *s;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ char *sid_string = NULL;
+ ssize_t sid_len;
+ ssize_t extra_data_len = 0;
+ char * extra_data = NULL;
+ ssize_t buflen = 0;
+ struct wbcDomainSid sid;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ uint32_t * rids = NULL;
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (!dom_sid) {
+ wbc_status = WBC_ERR_INVALID_PARAM;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ wbc_status = wbcSidToString(dom_sid, &sid_string);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1);
+ wbcFreeMemory(sid_string);
+ sid_string = NULL;
+
+ /* Lets assume each sid is around 54 characters
+ * S-1-5-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
+ buflen = 54 * num_sids;
+ extra_data = talloc_array(NULL, char, buflen);
+ if (!extra_data) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ /* Build the sid list */
+ for (i=0; i<num_sids; i++) {
+ if (sid_string) {
+ wbcFreeMemory(sid_string);
+ sid_string = NULL;
+ }
+ wbc_status = wbcSidToString(&sids[i], &sid_string);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ sid_len = strlen(sid_string);
+
+ if (buflen < extra_data_len + sid_len + 2) {
+ buflen *= 2;
+ extra_data = talloc_realloc(NULL, extra_data,
+ char, buflen);
+ if (!extra_data) {
+ wbc_status = WBC_ERR_NO_MEMORY;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+ }
+
+ strncpy(&extra_data[extra_data_len], sid_string,
+ buflen - extra_data_len);
+ extra_data_len += sid_len;
+ extra_data[extra_data_len++] = '\n';
+ extra_data[extra_data_len] = '\0';
+ }
+
+ request.extra_data.data = extra_data;
+ request.extra_len = extra_data_len;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETSIDALIASES,
+ &request,
+ &response);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ if (response.data.num_entries &&
+ !response.extra_data.data) {
+ wbc_status = WBC_ERR_INVALID_RESPONSE;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ rids = talloc_array(NULL, uint32_t,
+ response.data.num_entries);
+ BAIL_ON_PTR_ERROR(sids, wbc_status);
+
+ s = (const char *)response.extra_data.data;
+ for (i = 0; i < response.data.num_entries; i++) {
+ char *n = strchr(s, '\n');
+ if (n) {
+ *n = '\0';
+ }
+ wbc_status = wbcStringToSid(s, &sid);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ wbc_status = _sid_to_rid(&sid, &rids[i]);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ s += strlen(s) + 1;
+ }
+
+ *num_alias_rids = response.data.num_entries;
+ *alias_rids = rids;
+ rids = NULL;
+ wbc_status = WBC_ERR_SUCCESS;
+
+ done:
+ if (sid_string) {
+ wbcFreeMemory(sid_string);
+ }
+ if (extra_data) {
+ talloc_free(extra_data);
+ }
+ if (response.extra_data.data) {
+ free(response.extra_data.data);
+ }
+ if (rids) {
+ talloc_free(rids);
+ }
+
+ return wbc_status;
+}
+
+
/* Lists Users */
wbcErr wbcListUsers(const char *domain_name,
uint32_t *_num_users,
diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h
index 4663624f91..9d29951ae5 100644
--- a/nsswitch/libwbclient/wbclient.h
+++ b/nsswitch/libwbclient/wbclient.h
@@ -61,6 +61,7 @@ const char *wbcErrorString(wbcErr error);
* 0.2: Added wbcRemoveUidMapping()
* Added wbcRemoveGidMapping()
* 0.3: Added wbcGetpwsid()
+ * Added wbcGetSidAliases()
**/
#define WBCLIENT_MAJOR_VERSION 0
#define WBCLIENT_MINOR_VERSION 3
@@ -616,6 +617,15 @@ wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
uint32_t *num_sids,
struct wbcDomainSid **sids);
+/*
+ * @brief Get alias membership for sids
+ **/
+wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
+ struct wbcDomainSid *sids,
+ uint32_t num_sids,
+ uint32_t **alias_rids,
+ uint32_t *num_alias_rids);
+
/**
* @brief Lists Users
**/
diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index 372896ce71..4d935f5239 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -366,6 +366,64 @@ static bool wbinfo_get_userdomgroups(const char *user_sid_str)
return true;
}
+static bool wbinfo_get_sidaliases(const char *domain,
+ const char *user_sid_str)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainInfo *dinfo = NULL;
+ uint32_t i;
+ struct wbcDomainSid user_sid;
+ uint32_t *alias_rids = NULL;
+ uint32_t num_alias_rids;
+ char *domain_sid_str = NULL;
+
+ /* Send request */
+ if ((domain == NULL) || (strequal(domain, ".")) ||
+ (domain[0] == '\0')) {
+ domain = get_winbind_domain();
+ }
+
+ /* Send request */
+
+ wbc_status = wbcDomainInfo(domain, &dinfo);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ d_printf("wbcDomainInfo(%s) failed: %s\n", domain,
+ wbcErrorString(wbc_status));
+ goto done;
+ }
+ wbc_status = wbcStringToSid(user_sid_str, &user_sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ wbc_status = wbcGetSidAliases(&dinfo->sid, &user_sid, 1,
+ &alias_rids, &num_alias_rids);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ wbc_status = wbcSidToString(&dinfo->sid, &domain_sid_str);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ for (i = 0; i < num_alias_rids; i++) {
+ d_printf("%s-%d\n", domain_sid_str, alias_rids[i]);
+ }
+
+ wbcFreeMemory(alias_rids);
+
+done:
+ if (domain_sid_str) {
+ wbcFreeMemory(domain_sid_str);
+ }
+ if (dinfo) {
+ wbcFreeMemory(dinfo);
+ }
+ return (WBC_ERR_SUCCESS == wbc_status);
+}
+
+
/* Convert NetBIOS name to IP */
static bool wbinfo_wins_byname(const char *name)
@@ -1578,6 +1636,7 @@ enum {
OPT_GETDCNAME,
OPT_DSGETDCNAME,
OPT_USERDOMGROUPS,
+ OPT_SIDALIASES,
OPT_USERSIDS,
OPT_ALLOCATE_UID,
OPT_ALLOCATE_GID,
@@ -1653,6 +1712,7 @@ int main(int argc, char **argv, char **envp)
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
{ "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
+ { "sid-aliases", 0, POPT_ARG_STRING, &string_arg, OPT_SIDALIASES, "Get sid aliases", "SID" },
{ "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
{ "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
{ "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" },
@@ -1936,6 +1996,13 @@ int main(int argc, char **argv, char **envp)
goto done;
}
break;
+ case OPT_SIDALIASES:
+ if (!wbinfo_get_sidaliases(opt_domain_name, string_arg)) {
+ d_fprintf(stderr, "Could not get sid aliases "
+ "for user SID %s\n", string_arg);
+ goto done;
+ }
+ break;
case 'a': {
bool got_error = false;
diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h
index 26e45f3c7f..11b2069c3a 100644
--- a/nsswitch/winbind_struct_protocol.h
+++ b/nsswitch/winbind_struct_protocol.h
@@ -143,6 +143,9 @@ enum winbindd_cmd {
/* Various group queries */
WINBINDD_GETUSERDOMGROUPS,
+ /* lookup local groups */
+ WINBINDD_GETSIDALIASES,
+
/* Initialize connection in a child */
WINBINDD_INIT_CONNECTION,