summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2010-01-09 20:20:36 +0100
committerVolker Lendecke <vl@samba.org>2010-01-24 20:32:16 +0100
commit7d18d058a1203ab7079f9dbdf37962803064d699 (patch)
tree44b5e54adfe02dccd954570ad5993c3dceed9475
parent185815a6472a7a09602b3c51198e20257241dfa7 (diff)
downloadsamba-7d18d058a1203ab7079f9dbdf37962803064d699.tar.gz
samba-7d18d058a1203ab7079f9dbdf37962803064d699.tar.bz2
samba-7d18d058a1203ab7079f9dbdf37962803064d699.zip
s3: Add wbinfo --ccache-save
With this command you can give winbind your password for later use by the automatic ntlm_auth
-rw-r--r--nsswitch/libwbclient/wbc_pam.c18
-rw-r--r--nsswitch/libwbclient/wbclient.h10
-rw-r--r--nsswitch/wbinfo.c46
-rw-r--r--nsswitch/winbind_struct_protocol.h9
-rw-r--r--source3/winbindd/winbindd.c1
-rw-r--r--source3/winbindd/winbindd_ccache_access.c72
-rw-r--r--source3/winbindd/winbindd_domain.c4
-rw-r--r--source3/winbindd/winbindd_proto.h3
8 files changed, 162 insertions, 1 deletions
diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c
index 1f76c0a143..087db2e6c6 100644
--- a/nsswitch/libwbclient/wbc_pam.c
+++ b/nsswitch/libwbclient/wbc_pam.c
@@ -1119,3 +1119,21 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
{
return WBC_ERR_NOT_IMPLEMENTED;
}
+
+/* Authenticate a user with cached credentials */
+wbcErr wbcCredentialSave(const char *user, const char *password)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ strncpy(request.data.ccache_save.user, user,
+ sizeof(request.data.ccache_save.user)-1);
+ strncpy(request.data.ccache_save.pass, password,
+ sizeof(request.data.ccache_save.pass)-1);
+ request.data.ccache_save.uid = getuid();
+
+ return wbcRequestResponse(WINBINDD_CCACHE_SAVE, &request, &response);
+}
diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h
index 33a4ace75c..06f0713c86 100644
--- a/nsswitch/libwbclient/wbclient.h
+++ b/nsswitch/libwbclient/wbclient.h
@@ -1164,6 +1164,16 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
struct wbcCredentialCacheInfo **info,
struct wbcAuthErrorInfo **error);
+/**
+ * @brief Save a password with winbind for doing wbcCredentialCache() later
+ *
+ * @param *user Username
+ * @param *password Password
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcCredentialSave(const char *user, const char *password);
+
/**********************************************************
* Resolve functions
**********************************************************/
diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index 45d8684bad..a43ce8f4c9 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -1530,6 +1530,43 @@ static bool wbinfo_auth_crap(char *username, bool use_ntlmv2, bool use_lanman)
return WBC_ERROR_IS_OK(wbc_status);
}
+/* Save creds with winbind */
+
+static bool wbinfo_ccache_save(char *username)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ char *s = NULL;
+ char *p = NULL;
+ char *password = NULL;
+ char *name = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ s = talloc_strdup(frame, username);
+ if (s == NULL) {
+ return false;
+ }
+
+ p = strchr(s, '%');
+ if (p != NULL) {
+ *p = 0;
+ p++;
+ password = talloc_strdup(frame, p);
+ } else {
+ password = wbinfo_prompt_pass(frame, NULL, username);
+ }
+
+ name = s;
+
+ wbc_status = wbcCredentialSave(name, password);
+
+ d_printf("saving creds %s\n",
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ TALLOC_FREE(frame);
+
+ return WBC_ERROR_IS_OK(wbc_status);
+}
+
#ifdef WITH_FAKE_KASERVER
/* Authenticate a user with a plaintext password and set a token */
@@ -1736,6 +1773,7 @@ enum {
OPT_ONLINESTATUS,
OPT_CHANGE_USER_PASSWORD,
OPT_PING_DC,
+ OPT_CCACHE_SAVE,
OPT_SID_TO_FULLNAME,
OPT_NTLMV2,
OPT_LANMAN
@@ -1805,6 +1843,9 @@ int main(int argc, char **argv, char **envp)
{ "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" },
+ { "ccache-save", 0, POPT_ARG_STRING, &string_arg,
+ OPT_CCACHE_SAVE, "Store user and password for ccache "
+ "operation", "user%password" },
{ "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
"Get a DC name for a foreign domain", "domainname" },
{ "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" },
@@ -2189,6 +2230,11 @@ int main(int argc, char **argv, char **envp)
wbinfo_get_auth_user();
goto done;
break;
+ case OPT_CCACHE_SAVE:
+ if (!wbinfo_ccache_save(string_arg)) {
+ goto done;
+ }
+ break;
case OPT_GETDCNAME:
if (!wbinfo_getdcname(string_arg)) {
goto done;
diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h
index 4d27d5283c..7790155f25 100644
--- a/nsswitch/winbind_struct_protocol.h
+++ b/nsswitch/winbind_struct_protocol.h
@@ -48,8 +48,9 @@ typedef char fstring[FSTRING_LEN];
* 21: added WINBINDD_GETPWSID
* added WINBINDD_GETSIDALIASES
* 22: added WINBINDD_PING_DC
+ * 23: added WINBINDD_CCACHE_SAVE
*/
-#define WINBIND_INTERFACE_VERSION 22
+#define WINBIND_INTERFACE_VERSION 23
/* 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
@@ -177,6 +178,7 @@ enum winbindd_cmd {
/* Complete the challenge phase of the NTLM authentication
protocol using cached password. */
WINBINDD_CCACHE_NTLMAUTH,
+ WINBINDD_CCACHE_SAVE,
WINBINDD_NUM_CMDS
};
@@ -335,6 +337,11 @@ struct winbindd_request {
uint32_t challenge_blob_len;
} ccache_ntlm_auth;
struct {
+ uid_t uid;
+ fstring user;
+ fstring pass;
+ } ccache_save;
+ struct {
fstring domain_name;
fstring domain_guid;
fstring site_name;
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index f6f4a8fee7..c0b42b811d 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -451,6 +451,7 @@ static struct winbindd_dispatch_table {
/* Credential cache access */
{ WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
+ { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
/* WINS functions */
diff --git a/source3/winbindd/winbindd_ccache_access.c b/source3/winbindd/winbindd_ccache_access.c
index 2f71aaae52..b0efc6474b 100644
--- a/source3/winbindd/winbindd_ccache_access.c
+++ b/source3/winbindd/winbindd_ccache_access.c
@@ -278,3 +278,75 @@ enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *doma
process_result:
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
+
+void winbindd_ccache_save(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ fstring name_domain, name_user;
+
+ /* Ensure null termination */
+ state->request->data.ccache_save.user[
+ sizeof(state->request->data.ccache_save.user)-1]='\0';
+ state->request->data.ccache_save.pass[
+ sizeof(state->request->data.ccache_save.pass)-1]='\0';
+
+ DEBUG(3, ("[%5lu]: save passord of user %s\n",
+ (unsigned long)state->pid,
+ state->request->data.ccache_save.user));
+
+ /* Parse domain and username */
+
+ if (!canonicalize_username(state->request->data.ccache_ntlm_auth.user,
+ name_domain, name_user)) {
+ DEBUG(5,("winbindd_ccache_save: cannot parse domain and user "
+ "from name [%s]\n",
+ state->request->data.ccache_save.user));
+ request_error(state);
+ return;
+ }
+
+ domain = find_auth_domain(state->request->flags, name_domain);
+
+ if (domain == NULL) {
+ DEBUG(5, ("winbindd_ccache_save: can't get domain [%s]\n",
+ name_domain));
+ request_error(state);
+ return;
+ }
+
+ if (!check_client_uid(state, state->request->data.ccache_save.uid)) {
+ request_error(state);
+ return;
+ }
+
+ sendto_domain(state, domain);
+}
+
+enum winbindd_result winbindd_dual_ccache_save(
+ struct winbindd_domain *domain, struct winbindd_cli_state *state)
+{
+ NTSTATUS status = NT_STATUS_NOT_SUPPORTED;
+
+ /* Ensure null termination */
+ state->request->data.ccache_save.user[
+ sizeof(state->request->data.ccache_save.user)-1]='\0';
+ state->request->data.ccache_save.pass[
+ sizeof(state->request->data.ccache_save.pass)-1]='\0';
+
+ DEBUG(3, ("winbindd_dual_ccache_save: [%5lu]: save password of user "
+ "%s\n", (unsigned long)state->pid,
+ state->request->data.ccache_save.user));
+
+ status = winbindd_add_memory_creds(
+ state->request->data.ccache_save.user,
+ state->request->data.ccache_save.uid,
+ state->request->data.ccache_save.pass);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("winbindd_add_memory_creds failed %s\n",
+ nt_errstr(status)));
+ return WINBINDD_ERROR;
+ }
+
+ return WINBINDD_OK;
+}
diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c
index 45da57e132..2cb6e31a9e 100644
--- a/source3/winbindd/winbindd_domain.c
+++ b/source3/winbindd/winbindd_domain.c
@@ -67,6 +67,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = {
.struct_cmd = WINBINDD_CCACHE_NTLMAUTH,
.struct_fn = winbindd_dual_ccache_ntlm_auth,
},{
+ .name = "CCACHE_SAVE",
+ .struct_cmd = WINBINDD_CCACHE_SAVE,
+ .struct_fn = winbindd_dual_ccache_save,
+ },{
.name = "NDRCMD",
.struct_cmd = WINBINDD_DUAL_NDRCMD,
.struct_fn = winbindd_dual_ndrcmd,
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 93d5748c49..f6c4dade4a 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -180,6 +180,9 @@ void wcache_store_ndr(struct winbindd_domain *domain, uint32_t opnum,
void winbindd_ccache_ntlm_auth(struct winbindd_cli_state *state);
enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *domain,
struct winbindd_cli_state *state);
+void winbindd_ccache_save(struct winbindd_cli_state *state);
+enum winbindd_result winbindd_dual_ccache_save(
+ struct winbindd_domain *domain, struct winbindd_cli_state *state);
/* The following definitions come from winbindd/winbindd_cm.c */