s3: Add wbinfo --ccache-save
authorVolker Lendecke <vl@samba.org>
Sat, 9 Jan 2010 19:20:36 +0000 (20:20 +0100)
committerVolker Lendecke <vl@samba.org>
Sun, 24 Jan 2010 19:32:16 +0000 (20:32 +0100)
With this command you can give winbind your password for later use by
the automatic ntlm_auth

nsswitch/libwbclient/wbc_pam.c
nsswitch/libwbclient/wbclient.h
nsswitch/wbinfo.c
nsswitch/winbind_struct_protocol.h
source3/winbindd/winbindd.c
source3/winbindd/winbindd_ccache_access.c
source3/winbindd/winbindd_domain.c
source3/winbindd/winbindd_proto.h

index 1f76c0a143f6d0d78dc8c7a1baa4c089d243b464..087db2e6c6bb0f37d8eb0a85cae4471f2559af02 100644 (file)
@@ -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);
+}
index 33a4ace75c9b95f18a7469911e9276c0d2be05fe..06f0713c8604fc9f231c6f4812910199f98b0dde 100644 (file)
@@ -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
  **********************************************************/
index 45d8684bad9c0562aacd53ef1096bbb4fa844d21..a43ce8f4c96e70ddb932a1eb0602c571fdb8a710 100644 (file)
@@ -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;
index 4d27d5283c81e9b43b0632ee5a0831263d897147..7790155f251db928ce8c0a95e46139a03d6a53bd 100644 (file)
@@ -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
 };
@@ -334,6 +336,11 @@ struct winbindd_request {
                        uint32_t initial_blob_len; /* blobs in extra_data */
                        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;
index f6f4a8fee78c9f641a404f96922258bd1dd71403..c0b42b811d7bf9044819caee649993275e4a9547 100644 (file)
@@ -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 */
 
index 2f71aaae527c6a4ed3ba93fe9e145b4740359e4c..b0efc6474bf5377e7d5e024a482e59b25b892557 100644 (file)
@@ -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;
+}
index 45da57e1327073b6dda12c1038ecb7bfe1594d2e..2cb6e31a9ef7238e28dec2a42f93a3dfc07b7cc5 100644 (file)
@@ -66,6 +66,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = {
                .name           = "CCACHE_NTLM_AUTH",
                .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,
index 93d5748c4912b78b88278dce8c8c165d644f3ea4..f6c4dade4ac2fbed95ace7494cad875b43d4c12c 100644 (file)
@@ -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  */