summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-12-03 17:47:39 +1100
committerAndrew Tridgell <tridge@samba.org>2008-12-03 17:47:39 +1100
commita226d86dcec393b2cd657d5441c3041dfdf5cd8f (patch)
tree03ef7f3207607a4e5351bf50892b0a39dcf6f219 /source3/nsswitch
parent30eff4f31b497ac94d8ee02ee2ec24bc8865ce0d (diff)
parent85b8cccab072bab263061654b677bc84826646c9 (diff)
downloadsamba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.tar.gz
samba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.tar.bz2
samba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/libwbclient/wbc_idmap.c154
-rw-r--r--source3/nsswitch/libwbclient/wbc_pam.c15
-rw-r--r--source3/nsswitch/libwbclient/wbc_pwd.c216
-rw-r--r--source3/nsswitch/libwbclient/wbclient.c2
-rw-r--r--source3/nsswitch/libwbclient/wbclient.h55
-rw-r--r--source3/nsswitch/pam_winbind.c187
-rw-r--r--source3/nsswitch/pam_winbind.h15
-rw-r--r--source3/nsswitch/wb_common.c2
-rw-r--r--source3/nsswitch/wbinfo.c181
-rw-r--r--source3/nsswitch/winbind_struct_protocol.h12
-rw-r--r--source3/nsswitch/wins.c63
11 files changed, 785 insertions, 117 deletions
diff --git a/source3/nsswitch/libwbclient/wbc_idmap.c b/source3/nsswitch/libwbclient/wbc_idmap.c
index 1615fd33ee..81b369c87c 100644
--- a/source3/nsswitch/libwbclient/wbc_idmap.c
+++ b/source3/nsswitch/libwbclient/wbc_idmap.c
@@ -24,7 +24,7 @@
#include "libwbclient.h"
-/** @brief Convert a Windows SID to a Unix uid
+/** @brief Convert a Windows SID to a Unix uid, allocating an uid if needed
*
* @param *sid Pointer to the domain SID to be resolved
* @param *puid Pointer to the resolved uid_t value
@@ -71,7 +71,22 @@ wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
return wbc_status;
}
-/** @brief Convert a Unix uid to a Windows SID
+/** @brief Convert a Windows SID to a Unix uid if there already is a mapping
+ *
+ * @param *sid Pointer to the domain SID to be resolved
+ * @param *puid Pointer to the resolved uid_t value
+ *
+ * @return #wbcErr
+ *
+ **/
+
+wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
+ uid_t *puid)
+{
+ return WBC_ERR_NOT_IMPLEMENTED;
+}
+
+/** @brief Convert a Unix uid to a Windows SID, allocating a SID if needed
*
* @param uid Unix uid to be resolved
* @param *sid Pointer to the resolved domain SID
@@ -112,7 +127,22 @@ done:
return wbc_status;
}
-/** @brief Convert a Windows SID to a Unix gid
+/** @brief Convert a Unix uid to a Windows SID if there already is a mapping
+ *
+ * @param uid Unix uid to be resolved
+ * @param *sid Pointer to the resolved domain SID
+ *
+ * @return #wbcErr
+ *
+ **/
+
+wbcErr wbcQueryUidToSid(uid_t uid,
+ struct wbcDomainSid *sid)
+{
+ return WBC_ERR_NOT_IMPLEMENTED;
+}
+
+/** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
*
* @param *sid Pointer to the domain SID to be resolved
* @param *pgid Pointer to the resolved gid_t value
@@ -159,7 +189,22 @@ wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
return wbc_status;
}
-/** @brief Convert a Unix uid to a Windows SID
+/** @brief Convert a Windows SID to a Unix gid if there already is a mapping
+ *
+ * @param *sid Pointer to the domain SID to be resolved
+ * @param *pgid Pointer to the resolved gid_t value
+ *
+ * @return #wbcErr
+ *
+ **/
+
+wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
+ gid_t *pgid)
+{
+ return WBC_ERR_NOT_IMPLEMENTED;
+}
+
+/** @brief Convert a Unix gid to a Windows SID, allocating a SID if needed
*
* @param gid Unix gid to be resolved
* @param *sid Pointer to the resolved domain SID
@@ -200,6 +245,21 @@ done:
return wbc_status;
}
+/** @brief Convert a Unix gid to a Windows SID if there already is a mapping
+ *
+ * @param gid Unix gid to be resolved
+ * @param *sid Pointer to the resolved domain SID
+ *
+ * @return #wbcErr
+ *
+ **/
+
+wbcErr wbcQueryGidToSid(gid_t gid,
+ struct wbcDomainSid *sid)
+{
+ return WBC_ERR_NOT_IMPLEMENTED;
+}
+
/** @brief Obtain a new uid from Winbind
*
* @param *puid *pointer to the allocated uid
@@ -362,6 +422,92 @@ wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid)
return wbc_status;
}
+/** @brief Remove a user id mapping
+ *
+ * @param uid Uid of the mapping to remove.
+ * @param *sid Pointer to the sid of the mapping to remove.
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ char *sid_string = NULL;
+
+ if (!sid) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ /* Make request */
+
+ request.data.dual_idmapset.id = uid;
+ request.data.dual_idmapset.type = _ID_TYPE_UID;
+
+ wbc_status = wbcSidToString(sid, &sid_string);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ strncpy(request.data.dual_idmapset.sid, sid_string,
+ sizeof(request.data.dual_idmapset.sid)-1);
+ wbcFreeMemory(sid_string);
+
+ wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING,
+ &request, &response);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ done:
+ return wbc_status;
+}
+
+/** @brief Remove a group id mapping
+ *
+ * @param gid Gid of the mapping to remove.
+ * @param *sid Pointer to the sid of the mapping to remove.
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ char *sid_string = NULL;
+
+ if (!sid) {
+ return WBC_ERR_INVALID_PARAM;
+ }
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ /* Make request */
+
+ request.data.dual_idmapset.id = gid;
+ request.data.dual_idmapset.type = _ID_TYPE_GID;
+
+ wbc_status = wbcSidToString(sid, &sid_string);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ strncpy(request.data.dual_idmapset.sid, sid_string,
+ sizeof(request.data.dual_idmapset.sid)-1);
+ wbcFreeMemory(sid_string);
+
+ wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING,
+ &request, &response);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ done:
+ return wbc_status;
+}
+
/** @brief Set the highwater mark for allocated uids.
*
* @param uid_hwm The new uid highwater mark value
diff --git a/source3/nsswitch/libwbclient/wbc_pam.c b/source3/nsswitch/libwbclient/wbc_pam.c
index 713ba2e65b..401d2ad2c3 100644
--- a/source3/nsswitch/libwbclient/wbc_pam.c
+++ b/source3/nsswitch/libwbclient/wbc_pam.c
@@ -1095,3 +1095,18 @@ done:
return wbc_status;
}
+
+/** @brief Authenticate a user with cached credentials
+ *
+ * @param *params Pointer to a wbcCredentialCacheParams structure
+ * @param **info Pointer to a pointer to a wbcCredentialCacheInfo structure
+ * @param **error Pointer to a pointer to a wbcAuthErrorInfo structure
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
+ struct wbcCredentialCacheInfo **info,
+ struct wbcAuthErrorInfo **error)
+{
+ return WBC_ERR_NOT_IMPLEMENTED;
+}
diff --git a/source3/nsswitch/libwbclient/wbc_pwd.c b/source3/nsswitch/libwbclient/wbc_pwd.c
index 0d17b312ef..d54a5af4fc 100644
--- a/source3/nsswitch/libwbclient/wbc_pwd.c
+++ b/source3/nsswitch/libwbclient/wbc_pwd.c
@@ -24,6 +24,16 @@
#include "libwbclient.h"
+/** @brief The maximum number of pwent structs to get from winbindd
+ *
+ */
+#define MAX_GETPWENT_USERS 500
+
+/** @brief The maximum number of grent structs to get from winbindd
+ *
+ */
+#define MAX_GETGRENT_GROUPS 500
+
/**
*
**/
@@ -284,6 +294,21 @@ wbcErr wbcGetgrgid(gid_t gid, struct group **grp)
return wbc_status;
}
+/** @brief Number of cached passwd structs
+ *
+ */
+static uint32_t pw_cache_size;
+
+/** @brief Position of the pwent context
+ *
+ */
+static uint32_t pw_cache_idx;
+
+/** @brief Winbindd response containing the passwd structs
+ *
+ */
+static struct winbindd_response pw_response;
+
/** @brief Reset the passwd iterator
*
* @return #wbcErr
@@ -293,6 +318,15 @@ wbcErr wbcSetpwent(void)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (pw_cache_size > 0) {
+ pw_cache_idx = pw_cache_size = 0;
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ }
+ }
+
+ ZERO_STRUCT(pw_response);
+
wbc_status = wbcRequestResponse(WINBINDD_SETPWENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
@@ -310,6 +344,13 @@ wbcErr wbcEndpwent(void)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (pw_cache_size > 0) {
+ pw_cache_idx = pw_cache_size = 0;
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ }
+ }
+
wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
@@ -320,16 +361,70 @@ wbcErr wbcEndpwent(void)
/** @brief Return the next struct passwd* entry from the pwent iterator
*
- * @param **pwd Pointer to resulting struct group* from the query.
+ * @param **pwd Pointer to resulting struct passwd* from the query.
*
* @return #wbcErr
**/
wbcErr wbcGetpwent(struct passwd **pwd)
{
- return WBC_ERR_NOT_IMPLEMENTED;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_pw *wb_pw;
+
+ /* If there's a cached result, return that. */
+ if (pw_cache_idx < pw_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ pw_cache_idx = 0;
+
+ if (pw_response.extra_data.data) {
+ free(pw_response.extra_data.data);
+ ZERO_STRUCT(pw_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETPWENT_USERS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request,
+ &pw_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ pw_cache_size = pw_response.data.num_entries;
+
+return_result:
+
+ wb_pw = (struct winbindd_pw *) pw_response.extra_data.data;
+
+ *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]);
+
+ BAIL_ON_PTR_ERROR(*pwd, wbc_status);
+
+ pw_cache_idx++;
+
+done:
+ return wbc_status;
}
+/** @brief Number of cached group structs
+ *
+ */
+static uint32_t gr_cache_size;
+
+/** @brief Position of the grent context
+ *
+ */
+static uint32_t gr_cache_idx;
+
+/** @brief Winbindd response containing the group structs
+ *
+ */
+static struct winbindd_response gr_response;
+
/** @brief Reset the group iterator
*
* @return #wbcErr
@@ -339,6 +434,15 @@ wbcErr wbcSetgrent(void)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (gr_cache_size > 0) {
+ gr_cache_idx = gr_cache_size = 0;
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ }
+ }
+
+ ZERO_STRUCT(gr_response);
+
wbc_status = wbcRequestResponse(WINBINDD_SETGRENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
@@ -356,6 +460,13 @@ wbcErr wbcEndgrent(void)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ if (gr_cache_size > 0) {
+ gr_cache_idx = gr_cache_size = 0;
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ }
+ }
+
wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT,
NULL, NULL);
BAIL_ON_WBC_ERROR(wbc_status);
@@ -364,7 +475,7 @@ wbcErr wbcEndgrent(void)
return wbc_status;
}
-/** @brief Return the next struct passwd* entry from the pwent iterator
+/** @brief Return the next struct group* entry from the pwent iterator
*
* @param **grp Pointer to resulting struct group* from the query.
*
@@ -373,7 +484,104 @@ wbcErr wbcEndgrent(void)
wbcErr wbcGetgrent(struct group **grp)
{
- return WBC_ERR_NOT_IMPLEMENTED;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_gr *wb_gr;
+ uint32_t mem_ofs;
+
+ /* If there's a cached result, return that. */
+ if (gr_cache_idx < gr_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ gr_cache_idx = 0;
+
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ ZERO_STRUCT(gr_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETGRENT_GROUPS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request,
+ &gr_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ gr_cache_size = gr_response.data.num_entries;
+
+return_result:
+
+ wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
+
+ mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs +
+ gr_cache_size * sizeof(struct winbindd_gr);
+
+ *grp = copy_group_entry(&wb_gr[gr_cache_idx],
+ ((char *)gr_response.extra_data.data)+mem_ofs);
+
+ BAIL_ON_PTR_ERROR(*grp, wbc_status);
+
+ gr_cache_idx++;
+
+done:
+ return wbc_status;
+}
+
+/** @brief Return the next struct group* entry from the pwent iterator
+ *
+ * This is similar to #wbcGetgrent, just that the member list is empty
+ *
+ * @param **grp Pointer to resulting struct group* from the query.
+ *
+ * @return #wbcErr
+ **/
+
+wbcErr wbcGetgrlist(struct group **grp)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct winbindd_request request;
+ struct winbindd_gr *wb_gr;
+
+ /* If there's a cached result, return that. */
+ if (gr_cache_idx < gr_cache_size) {
+ goto return_result;
+ }
+
+ /* Otherwise, query winbindd for some entries. */
+
+ gr_cache_idx = 0;
+
+ if (gr_response.extra_data.data) {
+ free(gr_response.extra_data.data);
+ ZERO_STRUCT(gr_response);
+ }
+
+ ZERO_STRUCT(request);
+ request.data.num_entries = MAX_GETGRENT_GROUPS;
+
+ wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request,
+ &gr_response);
+
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ gr_cache_size = gr_response.data.num_entries;
+
+return_result:
+
+ wb_gr = (struct winbindd_gr *) gr_response.extra_data.data;
+
+ *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL);
+
+ BAIL_ON_PTR_ERROR(*grp, wbc_status);
+
+ gr_cache_idx++;
+
+done:
+ return wbc_status;
}
/** @brief Return the unix group array belonging to the given user
diff --git a/source3/nsswitch/libwbclient/wbclient.c b/source3/nsswitch/libwbclient/wbclient.c
index bdde562a93..c0b7e0675a 100644
--- a/source3/nsswitch/libwbclient/wbclient.c
+++ b/source3/nsswitch/libwbclient/wbclient.c
@@ -59,7 +59,7 @@ wbcErr wbcRequestResponse(int cmd,
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
NSS_STATUS nss_status;
- /* for some calls the request and/or response cna be NULL */
+ /* for some calls the request and/or response can be NULL */
nss_status = winbindd_request_response(cmd, request, response);
diff --git a/source3/nsswitch/libwbclient/wbclient.h b/source3/nsswitch/libwbclient/wbclient.h
index 662e0cdf8d..cb31360407 100644
--- a/source3/nsswitch/libwbclient/wbclient.h
+++ b/source3/nsswitch/libwbclient/wbclient.h
@@ -57,9 +57,12 @@ const char *wbcErrorString(wbcErr error);
/**
* @brief Some useful details about the wbclient library
*
+ * 0.1: Initial version
+ * 0.2: Added wbcRemoveUidMapping()
+ * Added wbcRemoveGidMapping()
**/
#define WBCLIENT_MAJOR_VERSION 0
-#define WBCLIENT_MINOR_VERSION 1
+#define WBCLIENT_MINOR_VERSION 2
#define WBCLIENT_VENDOR_VERSION "Samba libwbclient"
struct wbcLibraryDetails {
uint16_t major_version;
@@ -358,7 +361,7 @@ struct wbcLogonUserInfo {
#define WBC_AUTH_USER_INFO_NOENCRYPTION 0x00000002
#define WBC_AUTH_USER_INFO_CACHED_ACCOUNT 0x00000004
#define WBC_AUTH_USER_INFO_USED_LM_PASSWORD 0x00000008
-#define WBC_AUTH_USER_INFO_EXTRA_SIDS 0x00000020
+#define WBC_AUTH_USER_INFO_EXTRA_SIDS 0x00000020
#define WBC_AUTH_USER_INFO_SUBAUTH_SESSION_KEY 0x00000040
#define WBC_AUTH_USER_INFO_SERVER_TRUST_ACCOUNT 0x00000080
#define WBC_AUTH_USER_INFO_NTLMV2_ENABLED 0x00000100
@@ -385,7 +388,7 @@ struct wbcLogonUserInfo {
#define WBC_ACB_NOT_DELEGATED 0x00004000 /* 1 Not delegated */
#define WBC_ACB_USE_DES_KEY_ONLY 0x00008000 /* 1 Use DES key only */
#define WBC_ACB_DONT_REQUIRE_PREAUTH 0x00010000 /* 1 Preauth not required */
-#define WBC_ACB_PW_EXPIRED 0x00020000 /* 1 Password Expired */
+#define WBC_ACB_PW_EXPIRED 0x00020000 /* 1 Password Expired */
#define WBC_ACB_NO_AUTH_DATA_REQD 0x00080000 /* 1 = No authorization data required */
struct wbcAuthErrorInfo {
@@ -437,6 +440,30 @@ struct wbcLogoffUserParams {
struct wbcNamedBlob *blobs;
};
+/** @brief Credential cache log-on parameters
+ *
+ */
+
+struct wbcCredentialCacheParams {
+ const char *account_name;
+ const char *domain_name;
+ enum wbcCredentialCacheLevel {
+ WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP = 1
+ } level;
+ size_t num_blobs;
+ struct wbcNamedBlob *blobs;
+};
+
+
+/** @brief Info returned by credential cache auth
+ *
+ */
+
+struct wbcCredentialCacheInfo {
+ size_t num_blobs;
+ struct wbcNamedBlob *blobs;
+};
+
/*
* DomainControllerInfo struct
*/
@@ -538,15 +565,27 @@ wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
wbcErr wbcSidToUid(const struct wbcDomainSid *sid,
uid_t *puid);
+wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
+ uid_t *puid);
+
wbcErr wbcUidToSid(uid_t uid,
struct wbcDomainSid *sid);
+wbcErr wbcQueryUidToSid(uid_t uid,
+ struct wbcDomainSid *sid);
+
wbcErr wbcSidToGid(const struct wbcDomainSid *sid,
gid_t *pgid);
+wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
+ gid_t *pgid);
+
wbcErr wbcGidToSid(gid_t gid,
struct wbcDomainSid *sid);
+wbcErr wbcQueryGidToSid(gid_t gid,
+ struct wbcDomainSid *sid);
+
wbcErr wbcAllocateUid(uid_t *puid);
wbcErr wbcAllocateGid(gid_t *pgid);
@@ -555,6 +594,10 @@ wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid);
wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid);
+wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid);
+
+wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid);
+
wbcErr wbcSetUidHwm(uid_t uid_hwm);
wbcErr wbcSetGidHwm(gid_t gid_hwm);
@@ -583,6 +626,8 @@ wbcErr wbcEndgrent(void);
wbcErr wbcGetgrent(struct group **grp);
+wbcErr wbcGetgrlist(struct group **grp);
+
wbcErr wbcGetGroups(const char *account,
uint32_t *num_groups,
gid_t **_groups);
@@ -662,6 +707,10 @@ wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
enum wbcPasswordChangeRejectReason *reject_reason,
struct wbcUserPasswordPolicyInfo **policy);
+wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
+ struct wbcCredentialCacheInfo **info,
+ struct wbcAuthErrorInfo **error);
+
/*
* Resolve functions
*/
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index 1c927259e5..be22ff3f5e 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -147,6 +147,21 @@ static const char *_pam_error_code_str(int err)
#define MAX_PASSWD_TRIES 3
+#ifdef HAVE_GETTEXT
+static char initialized = 0;
+
+static inline void textdomain_init(void);
+static inline void textdomain_init(void)
+{
+ if (!initialized) {
+ bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
+ initialized = 1;
+ }
+ return;
+}
+#endif
+
+
/*
* Work around the pam API that has functions with void ** as parameters
* These lead to strict aliasing warnings with gcc.
@@ -515,6 +530,10 @@ static int _pam_winbind_init_context(pam_handle_t *pamh,
{
struct pwb_context *r = NULL;
+#ifdef HAVE_GETTEXT
+ textdomain_init();
+#endif
+
r = TALLOC_ZERO_P(NULL, struct pwb_context);
if (!r) {
return PAM_BUF_ERR;
@@ -557,44 +576,44 @@ static const struct ntstatus_errors {
const char *error_string;
} ntstatus_errors[] = {
{"NT_STATUS_OK",
- "Success"},
+ N_("Success")},
{"NT_STATUS_BACKUP_CONTROLLER",
- "No primary Domain Controler available"},
+ N_("No primary Domain Controler available")},
{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
- "No domain controllers found"},
+ N_("No domain controllers found")},
{"NT_STATUS_NO_LOGON_SERVERS",
- "No logon servers"},
+ N_("No logon servers")},
{"NT_STATUS_PWD_TOO_SHORT",
- "Password too short"},
+ N_("Password too short")},
{"NT_STATUS_PWD_TOO_RECENT",
- "The password of this user is too recent to change"},
+ N_("The password of this user is too recent to change")},
{"NT_STATUS_PWD_HISTORY_CONFLICT",
- "Password is already in password history"},
+ N_("Password is already in password history")},
{"NT_STATUS_PASSWORD_EXPIRED",
- "Your password has expired"},
+ N_("Your password has expired")},
{"NT_STATUS_PASSWORD_MUST_CHANGE",
- "You need to change your password now"},
+ N_("You need to change your password now")},
{"NT_STATUS_INVALID_WORKSTATION",
- "You are not allowed to logon from this workstation"},
+ N_("You are not allowed to logon from this workstation")},
{"NT_STATUS_INVALID_LOGON_HOURS",
- "You are not allowed to logon at this time"},
+ N_("You are not allowed to logon at this time")},
{"NT_STATUS_ACCOUNT_EXPIRED",
- "Your account has expired. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Your account has expired. "
+ "Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_ACCOUNT_DISABLED",
- "Your account is disabled. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Your account is disabled. "
+ "Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_ACCOUNT_LOCKED_OUT",
- "Your account has been locked. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Your account has been locked. "
+ "Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_ACCESS_DENIED",
- "Access is denied"},
+ N_("Access is denied")},
{NULL, NULL}
};
@@ -604,7 +623,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string)
for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
if (!strcasecmp(ntstatus_errors[i].ntstatus_string,
nt_status_string)) {
- return ntstatus_errors[i].error_string;
+ return _(ntstatus_errors[i].error_string);
}
}
return NULL;
@@ -832,14 +851,14 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
if (days == 0) {
_make_remark(ctx, PAM_TEXT_INFO,
- "Your password expires today");
+ _("Your password expires today"));
return true;
}
if (days > 0 && days < warn_pwd_expire) {
_make_remark_format(ctx, PAM_TEXT_INFO,
- "Your password will expire in %d %s",
- days, (days > 1) ? "days":"day");
+ _("Your password will expire in %d %s"),
+ days, (days > 1) ? _("days"):_("day"));
return true;
}
@@ -1231,9 +1250,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Grace login. "
- "Please change your password as soon you're "
- "online again");
+ _("Grace login. "
+ "Please change your password as soon you're "
+ "online again"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s logged on using grace logon\n",
username);
@@ -1241,9 +1260,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Domain Controller unreachable, "
- "using cached credentials instead. "
- "Network resources may be unavailable");
+ _("Domain Controller unreachable, "
+ "using cached credentials instead. "
+ "Network resources may be unavailable"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s logged on using cached credentials\n",
username);
@@ -1266,10 +1285,10 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx,
{
if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Failed to establish your Kerberos Ticket cache "
- "due time differences\n"
- "with the domain controller. "
- "Please verify the system time.\n");
+ _("Failed to establish your Kerberos Ticket cache "
+ "due time differences\n"
+ "with the domain controller. "
+ "Please verify the system time.\n"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s: Clock skew when getting Krb5 TGT\n",
username);
@@ -1334,14 +1353,14 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
goto failed;
}
- str = talloc_asprintf(ctx, "Your password ");
+ str = talloc_asprintf(ctx, _("Your password "));
if (!str) {
goto failed;
}
if (i->min_length_password > 0) {
str = talloc_asprintf_append(str,
- "must be at least %d characters; ",
+ _("must be at least %d characters; "),
i->min_length_password);
if (!str) {
goto failed;
@@ -1350,8 +1369,8 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
if (i->password_history > 0) {
str = talloc_asprintf_append(str,
- "cannot repeat any of your previous %d "
- "passwords; ",
+ _("cannot repeat any of your previous %d "
+ "passwords; "),
i->password_history);
if (!str) {
goto failed;
@@ -1360,19 +1379,19 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) {
str = talloc_asprintf_append(str,
- "must contain capitals, numerals "
- "or punctuation; "
- "and cannot contain your account "
- "or full name; ");
+ _("must contain capitals, numerals "
+ "or punctuation; "
+ "and cannot contain your account "
+ "or full name; "));
if (!str) {
goto failed;
}
}
str = talloc_asprintf_append(str,
- "Please type a different password. "
- "Type a password which meets these requirements in "
- "both text boxes.");
+ _("Please type a different password. "
+ "Type a password which meets these requirements in "
+ "both text boxes."));
if (!str) {
goto failed;
}
@@ -1397,7 +1416,7 @@ static int _pam_create_homedir(struct pwb_context *ctx,
if (mkdir(dirname, mode) != 0) {
_make_remark_format(ctx, PAM_TEXT_INFO,
- "Creating directory: %s failed: %s",
+ _("Creating directory: %s failed: %s"),
dirname, strerror(errno));
_pam_log(ctx, LOG_ERR, "could not create dir: %s (%s)",
dirname, strerror(errno));
@@ -1615,14 +1634,16 @@ static int winbind_auth_request(struct pwb_context *ctx,
logon.username = user;
logon.password = pass;
- wbc_status = wbcAddNamedBlob(&logon.num_blobs,
- &logon.blobs,
- "krb5_cc_type",
- 0,
- (uint8_t *)cctype,
- strlen(cctype)+1);
- if (!WBC_ERROR_IS_OK(wbc_status)) {
- goto done;
+ if (cctype) {
+ wbc_status = wbcAddNamedBlob(&logon.num_blobs,
+ &logon.blobs,
+ "krb5_cc_type",
+ 0,
+ (uint8_t *)cctype,
+ strlen(cctype)+1);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
}
wbc_status = wbcAddNamedBlob(&logon.num_blobs,
@@ -1645,14 +1666,16 @@ static int winbind_auth_request(struct pwb_context *ctx,
goto done;
}
- wbc_status = wbcAddNamedBlob(&logon.num_blobs,
- &logon.blobs,
- "membership_of",
- 0,
- (uint8_t *)membership_of,
- sizeof(membership_of));
- if (!WBC_ERROR_IS_OK(wbc_status)) {
- goto done;
+ if (member) {
+ wbc_status = wbcAddNamedBlob(&logon.num_blobs,
+ &logon.blobs,
+ "membership_of",
+ 0,
+ (uint8_t *)membership_of,
+ sizeof(membership_of));
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
}
wbc_status = wbcLogonUser(&logon, &info, &error, &policy);
@@ -1851,8 +1874,8 @@ static int winbind_chauthtok_request(struct pwb_context *ctx,
break;
case WBC_PWD_CHANGE_REJECT_COMPLEXITY:
_make_remark(ctx, PAM_ERROR_MSG,
- "Password does not meet "
- "complexity requirements");
+ _("Password does not meet "
+ "complexity requirements"));
break;
default:
_pam_log_debug(ctx, LOG_DEBUG,
@@ -2293,7 +2316,7 @@ static int _pam_delete_cred(pam_handle_t *pamh, int flags,
struct wbcLogoffUserParams logoff;
struct wbcAuthErrorInfo *error = NULL;
const char *user;
- wbcErr wbc_status;
+ wbcErr wbc_status = WBC_ERR_SUCCESS;
retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx);
if (retval) {
@@ -2310,7 +2333,7 @@ static int _pam_delete_cred(pam_handle_t *pamh, int flags,
const char *ccname = NULL;
struct passwd *pwd = NULL;
- retval = pam_get_user(pamh, &user, "Username: ");
+ retval = pam_get_user(pamh, &user, _("Username: "));
if (retval) {
_pam_log(ctx, LOG_ERR,
"could not identify user");
@@ -2346,14 +2369,16 @@ static int _pam_delete_cred(pam_handle_t *pamh, int flags,
logoff.username = user;
- wbc_status = wbcAddNamedBlob(&logoff.num_blobs,
- &logoff.blobs,
- "ccfilename",
- 0,
- (uint8_t *)ccname,
- strlen(ccname)+1);
- if (!WBC_ERROR_IS_OK(wbc_status)) {
- goto out;
+ if (ccname) {
+ wbc_status = wbcAddNamedBlob(&logoff.num_blobs,
+ &logoff.blobs,
+ "ccfilename",
+ 0,
+ (uint8_t *)ccname,
+ strlen(ccname)+1);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto out;
+ }
}
wbc_status = wbcAddNamedBlob(&logoff.num_blobs,
@@ -2485,7 +2510,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
}
retval = _winbind_read_password(ctx, ctx->ctrl, NULL,
- "Password: ", NULL,
+ _("Password: "), NULL,
&password);
if (retval != PAM_SUCCESS) {
@@ -2855,7 +2880,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/*
* First get the name of a user
*/
- ret = pam_get_user(pamh, &user, "Username: ");
+ ret = pam_get_user(pamh, &user, _("Username: "));
if (ret) {
_pam_log(ctx, LOG_ERR,
"password - could not identify user");
@@ -2893,7 +2918,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* instruct user what is happening */
-#define greeting "Changing password for"
+#define greeting _("Changing password for")
Announce = talloc_asprintf(ctx, "%s %s", greeting, user);
if (!Announce) {
_pam_log(ctx, LOG_CRIT,
@@ -2906,7 +2931,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD;
ret = _winbind_read_password(ctx, lctrl,
Announce,
- "(current) NT password: ",
+ _("(current) NT password: "),
NULL,
(const char **) &pass_old);
TALLOC_FREE(Announce);
@@ -2976,8 +3001,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
ret = _winbind_read_password(ctx, lctrl,
NULL,
- "Enter new NT password: ",
- "Retype new NT password: ",
+ _("Enter new NT password: "),
+ _("Retype new NT password: "),
(const char **)&pass_new);
if (ret != PAM_SUCCESS) {
diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
index cb6f450ccb..0656f5972e 100644
--- a/source3/nsswitch/pam_winbind.h
+++ b/source3/nsswitch/pam_winbind.h
@@ -9,6 +9,7 @@
#include "system/time.h"
#include <talloc.h>
#include "libwbclient/wbclient.h"
+#include "localedir.h"
#define MODULE_NAME "pam_winbind"
#define PAM_SM_AUTH
@@ -22,6 +23,10 @@
#include <iniparser.h>
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+
#ifndef LINUX
/* Solaris always uses dynamic pam modules */
@@ -101,12 +106,20 @@ do { \
#define WINBIND_WARN_PWD_EXPIRE 0x00002000
#define WINBIND_MKHOMEDIR 0x00004000
+#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
+#define _(string) dgettext(MODULE_NAME, string)
+#else
+#define _(string) string
+#endif
+
+#define N_(string) string
+
/*
* here is the string to inform the user that the new passwords they
* typed were not the same.
*/
-#define MISTYPED_PASS "Sorry, passwords do not match"
+#define MISTYPED_PASS _("Sorry, passwords do not match")
#define on(x, y) (x & y)
#define off(x, y) (!(x & y))
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c
index 6e6d2bbbf8..a1646215bd 100644
--- a/source3/nsswitch/wb_common.c
+++ b/source3/nsswitch/wb_common.c
@@ -314,7 +314,7 @@ static int winbind_open_pipe_sock(int recursing, int need_priv)
if ((need_priv != 0) && (is_privileged == 0)) {
winbind_close_sock();
}
-
+
if (winbindd_fd != -1) {
return winbindd_fd;
}
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 84f01e19ff..d14cfe94b7 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -75,7 +75,7 @@ static char winbind_separator_int(bool strict)
/* HACK: (this module should not call lp_ funtions) */
sep = *lp_winbind_separator();
}
-
+
return sep;
}
@@ -130,6 +130,31 @@ static bool parse_wbinfo_domain_user(const char *domuser, fstring domain,
return true;
}
+/* Parse string of "uid,sid" or "gid,sid" into separate int and string values.
+ * Return true if input was valid, false otherwise. */
+static bool parse_mapping_arg(char *arg, int *id, char **sid)
+{
+ char *tmp, *endptr;
+
+ if (!arg || !*arg)
+ return false;
+
+ tmp = strtok(arg, ",");
+ *sid = strtok(NULL, ",");
+
+ if (!tmp || !*tmp || !*sid || !**sid)
+ return false;
+
+ /* Because atoi() can return 0 on invalid input, which would be a valid
+ * UID/GID we must use strtol() and do error checking */
+ *id = strtol(tmp, &endptr, 10);
+
+ if (endptr[0] != '\0')
+ return false;
+
+ return true;
+}
+
/* pull pwent info for a given user */
static bool wbinfo_get_userinfo(char *user)
@@ -738,6 +763,102 @@ static bool wbinfo_allocate_gid(void)
return true;
}
+static bool wbinfo_set_uid_mapping(uid_t uid, const char *sid_str)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainSid sid;
+
+ /* Send request */
+
+ wbc_status = wbcStringToSid(sid_str, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ wbc_status = wbcSetUidMapping(uid, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ /* Display response */
+
+ d_printf("uid %d now mapped to sid %s\n", uid, sid_str);
+
+ return true;
+}
+
+static bool wbinfo_set_gid_mapping(gid_t gid, const char *sid_str)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainSid sid;
+
+ /* Send request */
+
+ wbc_status = wbcStringToSid(sid_str, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ wbc_status = wbcSetGidMapping(gid, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ /* Display response */
+
+ d_printf("gid %d now mapped to sid %s\n", gid, sid_str);
+
+ return true;
+}
+
+static bool wbinfo_remove_uid_mapping(uid_t uid, const char *sid_str)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainSid sid;
+
+ /* Send request */
+
+ wbc_status = wbcStringToSid(sid_str, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ wbc_status = wbcRemoveUidMapping(uid, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ /* Display response */
+
+ d_printf("Removed uid %d to sid %s mapping\n", uid, sid_str);
+
+ return true;
+}
+
+static bool wbinfo_remove_gid_mapping(gid_t gid, const char *sid_str)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainSid sid;
+
+ /* Send request */
+
+ wbc_status = wbcStringToSid(sid_str, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ wbc_status = wbcRemoveGidMapping(gid, &sid);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
+
+ /* Display response */
+
+ d_printf("Removed gid %d to sid %s mapping\n", gid, sid_str);
+
+ return true;
+}
+
/* Convert sid to string */
static bool wbinfo_lookupsid(const char *sid_str)
@@ -1414,6 +1535,10 @@ enum {
OPT_USERSIDS,
OPT_ALLOCATE_UID,
OPT_ALLOCATE_GID,
+ OPT_SET_UID_MAPPING,
+ OPT_SET_GID_MAPPING,
+ OPT_REMOVE_UID_MAPPING,
+ OPT_REMOVE_GID_MAPPING,
OPT_SEPARATOR,
OPT_LIST_ALL_DOMAINS,
OPT_LIST_OWN_DOMAIN,
@@ -1431,8 +1556,10 @@ int main(int argc, char **argv, char **envp)
TALLOC_CTX *frame = talloc_stackframe();
poptContext pc;
static char *string_arg;
+ char *string_subarg = NULL;
static char *opt_domain_name;
static int int_arg;
+ int int_subarg = -1;
int result = 1;
bool verbose = false;
@@ -1459,6 +1586,10 @@ int main(int argc, char **argv, char **envp)
"Get a new UID out of idmap" },
{ "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID,
"Get a new GID out of idmap" },
+ { "set-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_UID_MAPPING, "Create or modify uid to sid mapping in idmap", "UID,SID" },
+ { "set-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_GID_MAPPING, "Create or modify gid to sid mapping in idmap", "GID,SID" },
+ { "remove-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_UID_MAPPING, "Remove uid to sid mapping in idmap", "UID,SID" },
+ { "remove-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_GID_MAPPING, "Remove gid to sid mapping in idmap", "GID,SID" },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
{ "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
@@ -1473,7 +1604,7 @@ int main(int argc, char **argv, char **envp)
{ "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
OPT_USERDOMGROUPS, "Get user domain groups", "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" },
+ { "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" },
{ "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
"Get a DC name for a foreign domain", "domainname" },
@@ -1482,7 +1613,7 @@ int main(int argc, char **argv, char **envp)
{ "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
{ "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
#ifdef WITH_FAKE_KASERVER
- { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
+ { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
#endif
#ifdef HAVE_KRB5
{ "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
@@ -1534,7 +1665,7 @@ int main(int argc, char **argv, char **envp)
load_interfaces();
- pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
+ pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
POPT_CONTEXT_KEEP_FIRST);
while((opt = poptGetNextOpt(pc)) != -1) {
@@ -1627,6 +1758,48 @@ int main(int argc, char **argv, char **envp)
goto done;
}
break;
+ case OPT_SET_UID_MAPPING:
+ if (!parse_mapping_arg(string_arg, &int_subarg,
+ &string_subarg) ||
+ !wbinfo_set_uid_mapping(int_subarg, string_subarg))
+ {
+ d_fprintf(stderr, "Could not create or modify "
+ "uid to sid mapping\n");
+ goto done;
+ }
+ break;
+ case OPT_SET_GID_MAPPING:
+ if (!parse_mapping_arg(string_arg, &int_subarg,
+ &string_subarg) ||
+ !wbinfo_set_gid_mapping(int_subarg, string_subarg))
+ {
+ d_fprintf(stderr, "Could not create or modify "
+ "gid to sid mapping\n");
+ goto done;
+ }
+ break;
+ case OPT_REMOVE_UID_MAPPING:
+ if (!parse_mapping_arg(string_arg, &int_subarg,
+ &string_subarg) ||
+ !wbinfo_remove_uid_mapping(int_subarg,
+ string_subarg))
+ {
+ d_fprintf(stderr, "Could not remove uid to sid "
+ "mapping\n");
+ goto done;
+ }
+ break;
+ case OPT_REMOVE_GID_MAPPING:
+ if (!parse_mapping_arg(string_arg, &int_subarg,
+ &string_subarg) ||
+ !wbinfo_remove_gid_mapping(int_subarg,
+ string_subarg))
+ {
+ d_fprintf(stderr, "Could not remove gid to sid "
+ "mapping\n");
+ goto done;
+ }
+ break;
case 't':
if (!wbinfo_check_secret()) {
d_fprintf(stderr, "Could not check secret\n");
diff --git a/source3/nsswitch/winbind_struct_protocol.h b/source3/nsswitch/winbind_struct_protocol.h
index ff52dbddaf..36873f2096 100644
--- a/source3/nsswitch/winbind_struct_protocol.h
+++ b/source3/nsswitch/winbind_struct_protocol.h
@@ -41,7 +41,9 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 19
+/* Version 20: added WINBINDD_REMOVE_MAPPING command */
+
+#define WINBIND_INTERFACE_VERSION 20
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
On a 64bit Linux box, we have to support a constant structure size
@@ -95,7 +97,7 @@ enum winbindd_cmd {
/* Lookup functions */
- WINBINDD_SID_TO_UID,
+ WINBINDD_SID_TO_UID,
WINBINDD_SID_TO_GID,
WINBINDD_SIDS_TO_XIDS,
WINBINDD_UID_TO_SID,
@@ -104,6 +106,7 @@ enum winbindd_cmd {
WINBINDD_ALLOCATE_UID,
WINBINDD_ALLOCATE_GID,
WINBINDD_SET_MAPPING,
+ WINBINDD_REMOVE_MAPPING,
WINBINDD_SET_HWM,
/* Miscellaneous other stuff */
@@ -150,6 +153,7 @@ enum winbindd_cmd {
WINBINDD_DUAL_UID2SID,
WINBINDD_DUAL_GID2SID,
WINBINDD_DUAL_SET_MAPPING,
+ WINBINDD_DUAL_REMOVE_MAPPING,
WINBINDD_DUAL_SET_HWM,
/* Wrapper around possibly blocking unix nss calls */
@@ -202,7 +206,9 @@ typedef struct winbindd_gr {
#define WBFLAG_IS_PRIVILEGED 0x00000400 /* not used */
/* Flag to say this is a winbindd internal send - don't recurse. */
#define WBFLAG_RECURSE 0x00000800
-
+/* Flag to tell winbind the NTLMv2 blob is too big for the struct and is in the
+ * extra_data field */
+#define WBFLAG_BIG_NTLMV2_BLOB 0x00010000
#define WINBINDD_MAX_EXTRA_DATA (128*1024)
diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c
index 2f82997aaf..e028eb8cf2 100644
--- a/source3/nsswitch/wins.c
+++ b/source3/nsswitch/wins.c
@@ -24,6 +24,14 @@
#include <ns_daemon.h>
#endif
+#if HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#if HAVE_PTHREAD
+static pthread_mutex_t wins_nss_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
#ifndef INADDRSZ
#define INADDRSZ 4
#endif
@@ -320,11 +328,16 @@ NSS_STATUS
_nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
char *buffer, size_t buflen, int *h_errnop)
{
+ NSS_STATUS nss_status = NSS_STATUS_SUCCESS;
struct in_addr *ip_list;
int i, count;
fstring name;
size_t namelen;
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&wins_nss_mutex);
+#endif
+
memset(he, '\0', sizeof(*he));
fstrcpy(name, hostname);
@@ -332,8 +345,10 @@ _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
ip_list = lookup_byname_backend(name, &count);
- if (!ip_list)
- return NSS_STATUS_NOTFOUND;
+ if (!ip_list) {
+ nss_status = NSS_STATUS_NOTFOUND;
+ goto out;
+ }
/* Copy h_name */
@@ -341,7 +356,8 @@ _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) {
free(ip_list);
- return NSS_STATUS_TRYAGAIN;
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
}
memcpy(he->h_name, name, namelen);
@@ -353,20 +369,23 @@ _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
if (get_static(&buffer, &buflen, i) == NULL) {
free(ip_list);
- return NSS_STATUS_TRYAGAIN;
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
}
if ((he->h_addr_list = (char **)get_static(
&buffer, &buflen, (count + 1) * sizeof(char *))) == NULL) {
free(ip_list);
- return NSS_STATUS_TRYAGAIN;
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
}
for (i = 0; i < count; i++) {
if ((he->h_addr_list[i] = get_static(&buffer, &buflen,
INADDRSZ)) == NULL) {
free(ip_list);
- return NSS_STATUS_TRYAGAIN;
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
}
memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ);
}
@@ -385,16 +404,27 @@ _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0)
i = sizeof(char*) - i;
- if (get_static(&buffer, &buflen, i) == NULL)
- return NSS_STATUS_TRYAGAIN;
+ if (get_static(&buffer, &buflen, i) == NULL) {
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
+ }
if ((he->h_aliases = (char **)get_static(
- &buffer, &buflen, sizeof(char *))) == NULL)
- return NSS_STATUS_TRYAGAIN;
+ &buffer, &buflen, sizeof(char *))) == NULL) {
+ nss_status = NSS_STATUS_TRYAGAIN;
+ goto out;
+ }
he->h_aliases[0] = NULL;
- return NSS_STATUS_SUCCESS;
+ nss_status = NSS_STATUS_SUCCESS;
+
+ out:
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&wins_nss_mutex);
+#endif
+ return nss_status;
}
@@ -402,12 +432,15 @@ NSS_STATUS
_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he,
char *buffer, size_t buflen, int *h_errnop)
{
+ NSS_STATUS nss_status;
+
if(af!=AF_INET) {
*h_errnop = NO_DATA;
- return NSS_STATUS_UNAVAIL;
+ nss_status = NSS_STATUS_UNAVAIL;
+ } else {
+ nss_status = _nss_wins_gethostbyname_r(
+ name, he, buffer, buflen, h_errnop);
}
-
- return _nss_wins_gethostbyname_r(
- name, he, buffer, buflen, h_errnop);
+ return nss_status;
}
#endif