Copyright (C) Stefan Metzmacher 2005
Copyright (C) Volker Lendecke 2005
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+ Copyright (C) Kai Blin 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "includes.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
#include "param/param.h"
#include "winbind/wb_helper.h"
#include "libcli/composite/composite.h"
#include "version.h"
-#include "librpc/gen_ndr/netlogon.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
#include "libcli/security/security.h"
-#include "auth/pam_errors.h"
+#include "../libcli/auth/pam_errors.h"
#include "auth/credentials/credentials.h"
#include "smbd/service_task.h"
+/*
+ support the old Samba3 TXT form of the info3
+ */
+static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
+ struct wbsrv_samba3_call *s3call,
+ DATA_BLOB info3b)
+{
+ struct netr_SamInfo3 *info3;
+ char *ex;
+ uint32_t i;
+ enum ndr_err_code ndr_err;
+
+ info3 = talloc(mem_ctx, struct netr_SamInfo3);
+ NT_STATUS_HAVE_NO_MEMORY(info3);
+
+ /* The Samba3 protocol has a redundant 4 bytes at the start */
+ info3b.data += 4;
+ info3b.length -= 4;
+
+ ndr_err = ndr_pull_struct_blob(&info3b,
+ mem_ctx,
+ info3,
+ (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ s3call->response->data.auth.info3.logon_time =
+ nt_time_to_unix(info3->base.logon_time);
+ s3call->response->data.auth.info3.logoff_time =
+ nt_time_to_unix(info3->base.logoff_time);
+ s3call->response->data.auth.info3.kickoff_time =
+ nt_time_to_unix(info3->base.kickoff_time);
+ s3call->response->data.auth.info3.pass_last_set_time =
+ nt_time_to_unix(info3->base.last_password_change);
+ s3call->response->data.auth.info3.pass_can_change_time =
+ nt_time_to_unix(info3->base.allow_password_change);
+ s3call->response->data.auth.info3.pass_must_change_time =
+ nt_time_to_unix(info3->base.force_password_change);
+
+ s3call->response->data.auth.info3.logon_count = info3->base.logon_count;
+ s3call->response->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
+
+ s3call->response->data.auth.info3.user_rid = info3->base.rid;
+ s3call->response->data.auth.info3.group_rid = info3->base.primary_gid;
+ fstrcpy(s3call->response->data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));
+
+ s3call->response->data.auth.info3.num_groups = info3->base.groups.count;
+ s3call->response->data.auth.info3.user_flgs = info3->base.user_flags;
+
+ s3call->response->data.auth.info3.acct_flags = info3->base.acct_flags;
+ s3call->response->data.auth.info3.num_other_sids = info3->sidcount;
+
+ fstrcpy(s3call->response->data.auth.info3.user_name,
+ info3->base.account_name.string);
+ fstrcpy(s3call->response->data.auth.info3.full_name,
+ info3->base.full_name.string);
+ fstrcpy(s3call->response->data.auth.info3.logon_script,
+ info3->base.logon_script.string);
+ fstrcpy(s3call->response->data.auth.info3.profile_path,
+ info3->base.profile_path.string);
+ fstrcpy(s3call->response->data.auth.info3.home_dir,
+ info3->base.home_directory.string);
+ fstrcpy(s3call->response->data.auth.info3.dir_drive,
+ info3->base.home_drive.string);
+
+ fstrcpy(s3call->response->data.auth.info3.logon_srv,
+ info3->base.logon_server.string);
+ fstrcpy(s3call->response->data.auth.info3.logon_dom,
+ info3->base.logon_domain.string);
+
+ ex = talloc_strdup(mem_ctx, "");
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+
+ for (i=0; i < info3->base.groups.count; i++) {
+ ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
+ info3->base.groups.rids[i].rid,
+ info3->base.groups.rids[i].attributes);
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+ }
+
+ for (i=0; i < info3->sidcount; i++) {
+ char *sid;
+
+ sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid);
+
+ ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
+ sid,
+ info3->sids[i].attributes);
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+
+ talloc_free(sid);
+ }
+
+ s3call->response->extra_data.data = ex;
+ s3call->response->length += talloc_get_size(ex);
+
+ return NT_STATUS_OK;
+}
+
/*
Send off the reply to an async Samba3 query, handling filling in the PAM, NTSTATUS and string errors.
*/
static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
struct wbsrv_samba3_call *s3call)
{
- struct winbindd_response *resp = &s3call->response;
+ struct winbindd_response *resp = s3call->response;
if (!NT_STATUS_IS_OK(status)) {
resp->result = WINBINDD_ERROR;
} else {
static void wbsrv_samba3_async_epilogue(NTSTATUS status,
struct wbsrv_samba3_call *s3call)
{
- struct winbindd_response *resp = &s3call->response;
+ struct winbindd_response *resp = s3call->response;
if (NT_STATUS_IS_OK(status)) {
resp->result = WINBINDD_OK;
} else {
NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
+ DEBUG(3, ("request interface version (version = %d)\n", WINBIND_INTERFACE_VERSION));
+
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.interface_version = WINBIND_INTERFACE_VERSION;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.info.winbind_separator = *lp_winbind_separator(s3call->wbconn->lp_ctx);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.info.winbind_separator = *lpcfg_winbind_separator(s3call->wbconn->lp_ctx);
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.info.samba_version,
SAMBA_VERSION_STRING);
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name,
- lp_workgroup(s3call->wbconn->lp_ctx));
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.domain_name,
+ lpcfg_workgroup(s3call->wbconn->lp_ctx));
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name,
- lp_netbios_name(s3call->wbconn->lp_ctx));
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.netbios_name,
+ lpcfg_netbios_name(s3call->wbconn->lp_ctx));
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
{
- char *path = smbd_tmp_path(s3call, s3call->wbconn->lp_ctx, WINBINDD_SAMBA3_PRIVILEGED_SOCKET);
- NT_STATUS_HAVE_NO_MEMORY(path);
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = path;
-
- s3call->response.length += strlen(path) + 1;
+ struct loadparm_context *lp_ctx = s3call->wbconn->listen_socket->service->task->lp_ctx;
+ const char *priv_socket_dir = lpcfg_winbindd_privileged_socket_directory(lp_ctx);
+
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = discard_const(priv_socket_dir);
+
+ s3call->response->length += strlen(priv_socket_dir) + 1;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
+{
+ DEBUG(5, ("wbsrv_samba3_domain_info called, stub\n"));
+ s3call->response->result = WINBINDD_OK;
+ fstrcpy(s3call->response->data.domain_info.name,
+ s3call->request->domain_name);
+ fstrcpy(s3call->response->data.domain_info.alt_name,
+ s3call->request->domain_name);
+ fstrcpy(s3call->response->data.domain_info.sid, "S-1-2-3-4");
+ s3call->response->data.domain_info.native_mode = false;
+ s3call->response->data.domain_info.active_directory = false;
+ s3call->response->data.domain_info.primary = false;
+
return NT_STATUS_OK;
}
struct wbsrv_samba3_call);
NTSTATUS status;
- status = wb_cmd_pam_auth_recv(ctx);
+ status = wb_cmd_pam_auth_recv(ctx, s3call, NULL, NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) goto done;
DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
ctx = wb_cmd_getdcname_send(s3call, service,
- s3call->request.domain_name);
+ s3call->request->domain_name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getdcname_recv_dc;
status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.dc_name, dcname);
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.dc_name, dcname);
done:
wbsrv_samba3_async_epilogue(status, s3call);
DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_sids;
+ uint32_t i, num_sids;
struct dom_sid **sids;
char *sids_string;
NTSTATUS status;
goto done;
}
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = sids_string;
- s3call->response.length += strlen(sids_string)+1;
- s3call->response.data.num_entries = num_sids;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = sids_string;
+ s3call->response->length += strlen(sids_string)+1;
+ s3call->response->data.num_entries = num_sids;
done:
wbsrv_samba3_async_epilogue(status, s3call);
DEBUG(5, ("wbsrv_samba3_usersids called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_sids;
+ uint32_t i, num_sids;
struct dom_sid **sids;
char *sids_string;
NTSTATUS status;
}
}
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = sids_string;
- s3call->response.length += strlen(sids_string);
- s3call->response.data.num_entries = num_sids;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = sids_string;
+ s3call->response->length += strlen(sids_string);
+ s3call->response->data.num_entries = num_sids;
/* Hmmmm. Nasty protocol -- who invented the zeros between the
* SIDs? Hmmm. Could have been me -- vl */
DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
ctx = wb_cmd_lookupname_send(s3call, service,
- s3call->request.data.name.dom_name,
- s3call->request.data.name.name);
+ s3call->request->data.name.dom_name,
+ s3call->request->data.name.name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
/* setup the callbacks */
status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.sid.type = sid->type;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.sid.type = sid->type;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid,
dom_sid_string(s3call, sid->sid));
done:
DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.name.type = sid->type;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.dom_name,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.name.type = sid->type;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.dom_name,
sid->domain);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.name, sid->name);
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.name, sid->name);
done:
wbsrv_samba3_async_epilogue(status, s3call);
}
+/*
+ This is a stub function in order to limit error message in the pam_winbind module
+*/
+NTSTATUS wbsrv_samba3_pam_logoff(struct wbsrv_samba3_call *s3call)
+{
+ NTSTATUS status;
+ struct winbindd_response *resp = s3call->response;
+
+ status = NT_STATUS_OK;
+
+ DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
+ DEBUG(10, ("Winbind logoff not implemented\n"));
+ resp->result = WINBINDD_OK;
+
+ WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
+ nt_errstr(status));
+ WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
+ get_friendly_nt_error_msg(status));
+
+ resp->data.auth.pam_error = nt_status_to_pam(status);
+ resp->data.auth.nt_status = NT_STATUS_V(status);
+ DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
+
+ return NT_STATUS_OK;
+}
+
/*
Challenge-response authentication. This interface is used by
ntlm_auth and the smbd auth subsystem to pass NTLM authentication
The return value (in the async reply) may include the 'info3'
(effectivly most things you would want to know about the user), or
- the NT and LM session keys seperated.
+ the NT and LM session keys separated.
*/
static void pam_auth_crap_recv(struct composite_context *ctx);
DATA_BLOB chal, nt_resp, lm_resp;
DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
+ if (s3call->request->flags & WBFLAG_PAM_AUTH_PAC) {
+ DEBUG(3, ("PAC validation not supported in this winbind implementation\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- chal.data = s3call->request.data.auth_crap.chal;
- chal.length = sizeof(s3call->request.data.auth_crap.chal);
- nt_resp.data = (uint8_t *)s3call->request.data.auth_crap.nt_resp;
- nt_resp.length = s3call->request.data.auth_crap.nt_resp_len;
- lm_resp.data = (uint8_t *)s3call->request.data.auth_crap.lm_resp;
- lm_resp.length = s3call->request.data.auth_crap.lm_resp_len;
+ chal.data = s3call->request->data.auth_crap.chal;
+ chal.length = sizeof(s3call->request->data.auth_crap.chal);
+ nt_resp.data = (uint8_t *)s3call->request->data.auth_crap.nt_resp;
+ nt_resp.length = s3call->request->data.auth_crap.nt_resp_len;
+ lm_resp.data = (uint8_t *)s3call->request->data.auth_crap.lm_resp;
+ lm_resp.length = s3call->request->data.auth_crap.lm_resp_len;
ctx = wb_cmd_pam_auth_crap_send(
s3call, service,
- s3call->request.data.auth_crap.logon_parameters,
- s3call->request.data.auth_crap.domain,
- s3call->request.data.auth_crap.user,
- s3call->request.data.auth_crap.workstation,
+ s3call->request->data.auth_crap.logon_parameters,
+ s3call->request->data.auth_crap.domain,
+ s3call->request->data.auth_crap.user,
+ s3call->request->data.auth_crap.workstation,
chal, nt_resp, lm_resp);
NT_STATUS_HAVE_NO_MEMORY(ctx);
&user_session_key, &lm_key, &unix_username);
if (!NT_STATUS_IS_OK(status)) goto done;
- if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
- memcpy(s3call->response.data.auth.user_session_key,
+ if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
+ memcpy(s3call->response->data.auth.user_session_key,
&user_session_key.key,
- sizeof(s3call->response.data.auth.user_session_key));
+ sizeof(s3call->response->data.auth.user_session_key));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
+ status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
}
- if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
- s3call->response.extra_data.data = info3.data;
- s3call->response.length += info3.length;
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
+ s3call->response->extra_data.data = info3.data;
+ s3call->response->length += info3.length;
}
- if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
- memcpy(s3call->response.data.auth.first_8_lm_hash,
+ if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
+ memcpy(s3call->response->data.auth.first_8_lm_hash,
lm_key.key,
- sizeof(s3call->response.data.auth.first_8_lm_hash));
+ sizeof(s3call->response->data.auth.first_8_lm_hash));
}
- if (s3call->request.flags & WBFLAG_PAM_UNIX_NAME) {
- s3call->response.extra_data.data = unix_username;
- s3call->response.length += strlen(unix_username)+1;
+ if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
}
done:
char *user, *domain;
if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
- s3call->request.data.auth.user,
+ s3call->request->data.auth.user,
&domain, &user)) {
return NT_STATUS_NO_SUCH_USER;
}
cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
- cli_credentials_set_password(credentials, s3call->request.data.auth.pass, CRED_SPECIFIED);
+ cli_credentials_set_password(credentials, s3call->request->data.auth.pass, CRED_SPECIFIED);
ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
NT_STATUS_HAVE_NO_MEMORY(ctx);
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
NTSTATUS status;
+ DATA_BLOB info3;
+ struct netr_UserSessionKey user_session_key;
+ struct netr_LMSessionKey lm_key;
+ char *unix_username;
- status = wb_cmd_pam_auth_recv(ctx);
+ status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
+ &user_session_key, &lm_key, &unix_username);
if (!NT_STATUS_IS_OK(status)) goto done;
+ if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
+ memcpy(s3call->response->data.auth.user_session_key,
+ &user_session_key.key,
+ sizeof(s3call->response->data.auth.user_session_key));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
+ status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
+ s3call->response->extra_data.data = info3.data;
+ s3call->response->length += info3.length;
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
+ memcpy(s3call->response->data.auth.first_8_lm_hash,
+ lm_key.key,
+ sizeof(s3call->response->data.auth.first_8_lm_hash));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
+ }
+
+
done:
wbsrv_samba3_async_auth_epilogue(status, s3call);
}
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_domains;
+ uint32_t i, num_domains;
struct wb_dom_info **domains;
NTSTATUS status;
char *result;
goto done;
}
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
if (num_domains > 0) {
- s3call->response.extra_data.data = result;
- s3call->response.length += strlen(result)+1;
+ s3call->response->extra_data.data = result;
+ s3call->response->length += strlen(result)+1;
+ s3call->response->data.num_entries = num_domains;
}
done:
wbsrv_samba3_async_epilogue(status, s3call);
}
+/* list groups */
+static void list_groups_recv(struct composite_context *ctx);
+
+NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
+{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
+ DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
+
+ ctx = wb_cmd_list_groups_send(s3call, service,
+ s3call->request->domain_name);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = list_groups_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
+ return NT_STATUS_OK;
+}
+
+static void list_groups_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
+ ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ uint32_t extra_data_len;
+ char *extra_data;
+ uint32_t num_groups;
+ NTSTATUS status;
+
+ DEBUG(5, ("list_groups_recv called\n"));
+
+ status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
+ &extra_data, &num_groups);
+
+ if (NT_STATUS_IS_OK(status)) {
+ s3call->response->extra_data.data = extra_data;
+ s3call->response->length += extra_data_len;
+ if (extra_data) {
+ s3call->response->length += 1;
+ s3call->response->data.num_entries = num_groups;
+ }
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
/* List users */
DEBUG(5, ("wbsrv_samba3_list_users called\n"));
ctx = wb_cmd_list_users_send(s3call, service,
- s3call->request.domain_name);
+ s3call->request->domain_name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = list_users_recv;
struct wbsrv_samba3_call);
uint32_t extra_data_len;
char *extra_data;
+ uint32_t num_users;
NTSTATUS status;
DEBUG(5, ("list_users_recv called\n"));
status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
- &extra_data);
+ &extra_data, &num_users);
if (NT_STATUS_IS_OK(status)) {
- s3call->response.extra_data.data = extra_data;
- s3call->response.length += extra_data_len;
+ s3call->response->extra_data.data = extra_data;
+ s3call->response->length += extra_data_len;
if (extra_data) {
- s3call->response.length += 1;
+ s3call->response->length += 1;
+ s3call->response->data.num_entries = num_users;
}
}
DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
ctx = wb_cmd_getpwnam_send(s3call, service,
- s3call->request.data.username);
+ s3call->request->data.username);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwnam_recv;
status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
if(NT_STATUS_IS_OK(status))
- s3call->response.data.pw = *pw;
+ s3call->response->data.pw = *pw;
wbsrv_samba3_async_epilogue(status, s3call);
}
DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
ctx = wb_cmd_getpwuid_send(s3call, service,
- s3call->request.data.uid);
+ s3call->request->data.uid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwuid_recv;
status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
if (NT_STATUS_IS_OK(status))
- s3call->response.data.pw = *pw;
+ s3call->response->data.pw = *pw;
wbsrv_samba3_async_epilogue(status, s3call);
}
NT_STATUS_HAVE_NO_MEMORY(pwent);
ctx = wb_cmd_getpwent_send(s3call, service, pwent,
- s3call->request.data.num_entries);
+ s3call->request->data.num_entries);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwent_recv;
if (NT_STATUS_IS_OK(status)) {
uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
- s3call->response.data.num_entries = num_users;
- s3call->response.extra_data.data = pw;
- s3call->response.length += extra_len;
+ s3call->response->data.num_entries = num_users;
+ s3call->response->extra_data.data = pw;
+ s3call->response->length += extra_len;
}
wbsrv_samba3_async_epilogue(status, s3call);
talloc_free(pwent);
s3call->wbconn->protocol_private_data = NULL;
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
return NT_STATUS_OK;
}
+
+static void getgrnam_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service =
+ s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
- s3call->response.result = WINBINDD_ERROR;
+
+ ctx = wb_cmd_getgrnam_send(s3call, service,
+ s3call->request->data.groupname);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgrnam_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgrnam_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct winbindd_gr *gr;
+
+ DEBUG(5, ("getgrnam_recv called\n"));
+
+ status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
+ if(NT_STATUS_IS_OK(status))
+ s3call->response->data.gr = *gr;
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void getgrgid_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
- s3call->response.result = WINBINDD_ERROR;
+
+ ctx = wb_cmd_getgrgid_send(s3call, service,
+ s3call->request->data.gid);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgrgid_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgrgid_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct winbindd_gr *gr;
+
+ DEBUG(5, ("getgrgid_recv called\n"));
+
+ status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
+ if (NT_STATUS_IS_OK(status))
+ s3call->response->data.gr = *gr;
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void getgroups_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
- s3call->response.result = WINBINDD_ERROR;
+ /* S3 code do the same so why not ... */
+ s3call->request->data.username[sizeof(s3call->request->data.username)-1]='\0';
+ ctx = wb_cmd_getgroups_send(s3call, service, s3call->request->data.username);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgroups_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgroups_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ gid_t *gids;
+ uint32_t num_groups;
+ NTSTATUS status;
+ DEBUG(5, ("getgroups_recv called\n"));
+
+ status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
+ if (NT_STATUS_IS_OK(status)) {
+ uint32_t extra_len = sizeof(gid_t) * num_groups;
+
+ s3call->response->data.num_entries = num_groups;
+ s3call->response->extra_data.data = gids;
+ s3call->response->length += extra_len;
+ } else {
+ s3call->response->result = WINBINDD_ERROR;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void setgrent_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
- s3call->response.result = WINBINDD_OK;
+
+ ctx = wb_cmd_setgrent_send(s3call, service);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = setgrent_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void setgrent_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct wbsrv_grent *grent;
+
+ DEBUG(5, ("setpwent_recv called\n"));
+
+ status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
+ if (NT_STATUS_IS_OK(status)) {
+ s3call->wbconn->protocol_private_data = grent;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void getgrent_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+ struct wbsrv_grent *grent;
+
DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
- s3call->response.result = WINBINDD_ERROR;
+
+ NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
+
+ grent = talloc_get_type(s3call->wbconn->protocol_private_data,
+ struct wbsrv_grent);
+ NT_STATUS_HAVE_NO_MEMORY(grent);
+
+ ctx = wb_cmd_getgrent_send(s3call, service, grent,
+ s3call->request->data.num_entries);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgrent_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgrent_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct winbindd_gr *gr;
+ uint32_t num_groups;
+
+ DEBUG(5, ("getgrent_recv called\n"));
+
+ status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
+ if (NT_STATUS_IS_OK(status)) {
+ uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
+
+ s3call->response->data.num_entries = num_groups;
+ s3call->response->extra_data.data = gr;
+ s3call->response->length += extra_len;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
{
DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
return NT_STATUS_OK;
}
DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
NT_STATUS_HAVE_NO_MEMORY(sid);
ctx = wb_sid2uid_send(s3call, service, sid);
DEBUG(5, ("sid2uid_recv called\n"));
- status = wb_sid2uid_recv(ctx, &s3call->response.data.uid);
+ status = wb_sid2uid_recv(ctx, &s3call->response->data.uid);
wbsrv_samba3_async_epilogue(status, s3call);
}
DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
NT_STATUS_HAVE_NO_MEMORY(sid);
ctx = wb_sid2gid_send(s3call, service, sid);
DEBUG(5, ("sid2gid_recv called\n"));
- status = wb_sid2gid_recv(ctx, &s3call->response.data.gid);
+ status = wb_sid2gid_recv(ctx, &s3call->response->data.gid);
wbsrv_samba3_async_epilogue(status, s3call);
}
DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
- ctx = wb_uid2sid_send(s3call, service, s3call->request.data.uid);
+ ctx = wb_uid2sid_send(s3call, service, s3call->request->data.uid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = uid2sid_recv;
/* But we assume this worked, so we'll set the string. Work
* done. */
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
- s3call->response.data.sid.type = SID_NAME_USER;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
+ s3call->response->data.sid.type = SID_NAME_USER;
}
wbsrv_samba3_async_epilogue(status, s3call);
DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
- ctx = wb_gid2sid_send(s3call, service, s3call->request.data.gid);
+ ctx = wb_gid2sid_send(s3call, service, s3call->request->data.gid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = gid2sid_recv;
if (sid_str == NULL)
wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
- s3call->response.data.sid.type = SID_NAME_DOMAIN;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
+ s3call->response->data.sid.type = SID_NAME_DOMAIN;
}
wbsrv_samba3_async_epilogue(status, s3call);
}
+static void sids2xids_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct id_map *ids;
+ unsigned i, count;
+ struct winbindd_response *resp = s3call->response;
+
+ DEBUG(5, ("sids2xids_recv called\n"));
+
+ status = wb_sids2xids_recv(ctx, &ids, &count);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ /* fill in extra_data with the list of IDs. Each is prefixed
+ * by 'U' or 'G' for user and group, and followed by a
+ * newline */
+ resp->extra_data.data = talloc_strdup(resp, "");
+ if (resp->extra_data.data == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i<count; i++) {
+ char type_char = '*';
+ if (ids[i].status != ID_MAPPED) {
+ resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "\n");
+ if (resp->extra_data.data == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ continue;
+ }
+ switch (ids[i].xid.type) {
+ case ID_TYPE_UID:
+ type_char = 'U';
+ break;
+ case ID_TYPE_GID:
+ type_char = 'G';
+ break;
+ case ID_TYPE_BOTH:
+ type_char = 'B';
+ break;
+ case ID_TYPE_NOT_SPECIFIED:
+ type_char = 'N';
+ break;
+ }
+ resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "%c%u\n",
+ type_char, (unsigned)ids[i].xid.id);
+ if (resp->extra_data.data == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+ resp->length += strlen(resp->extra_data.data) + 1;
+
+done:
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+
+NTSTATUS wbsrv_samba3_sids2xids(struct wbsrv_samba3_call *s3call)
+{
+ struct composite_context *ctx;
+ struct wbsrv_service *service =
+ s3call->wbconn->listen_socket->service;
+ struct id_map *ids = NULL;
+ unsigned count = 0;
+ char *saveptr = NULL;
+ char *sidstr;
+
+ DEBUG(5, ("wbsrv_samba3_sids2xids called\n"));
+
+ for (sidstr = strtok_r(s3call->request->extra_data.data, "\n", &saveptr);
+ sidstr;
+ sidstr = strtok_r(NULL, "\n", &saveptr)) {
+ count += 1;
+ ids = talloc_realloc(s3call, ids, struct id_map, count);
+ NT_STATUS_HAVE_NO_MEMORY(ids);
+ ids[count-1].sid = dom_sid_parse_talloc(ids, sidstr);
+ NT_STATUS_HAVE_NO_MEMORY(ids->sid);
+ }
+
+ ctx = wb_sids2xids_send(s3call, service, count, ids);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = sids2xids_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
+ return NT_STATUS_OK;
+}