giving NT_STATUS_NO_MEMORY, when the connection fails wasn't a good idea...
metze
r13509@SERNOX (orig r10838): vlendec | 2005-10-08 19:45:27 +0200
Get us an schannel'ed netlogon pipe.
Abartlet, now I think I need some assistance to implement the pam auth & crap
auth calls.
Volker
r13510@SERNOX (orig r10839): jelmer | 2005-10-08 19:55:28 +0200
Add some [ref] (required for ethereal and Samba3 parser generators)
r13511@SERNOX (orig r10840): jelmer | 2005-10-08 19:55:56 +0200
Fix indentation
r13513@SERNOX (orig r10842): jelmer | 2005-10-08 22:19:35 +0200
Fix some issues with [out] unions that have a discriminator that is only
[in]
r13514@SERNOX (orig r10843): vlendec | 2005-10-09 10:32:06 +0200
Reformatting
r13515@SERNOX (orig r10844): abartlet | 2005-10-09 14:13:05 +0200
Add challenge-response authentication to Samba4's winbindd for VL.
Plaintext should be simple, but I'm going to do some infrustructure
work first.
Andrew Bartlett
r13516@SERNOX (orig r10845): abartlet | 2005-10-09 14:38:23 +0200
Add new function to decrypt the session keys in samlogon responses.
Andrew Bartlett
r13517@SERNOX (orig r10846): vlendec | 2005-10-09 14:50:35 +0200
Create a "wbsrv_domain", change wb_finddcs to the style of the rest of the
async helpers.
Volker
r13518@SERNOX (orig r10847): abartlet | 2005-10-09 15:03:52 +0200
Fix up new 'decrypt samlogon reply' routine to be more robust, and use
it in the RPC-SAMLOGON test.
Andrew Bartlett
r13519@SERNOX (orig r10848): jelmer | 2005-10-09 15:40:55 +0200
Fix warning
r13520@SERNOX (orig r10849): jelmer | 2005-10-09 15:53:48 +0200
Fix handling of [charset] for strings with fixed or "inline" size
r13523@SERNOX (orig r10852): vlendec | 2005-10-09 22:32:24 +0200
Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
r13524@SERNOX (orig r10853): vlendec | 2005-10-09 22:57:49 +0200
Convert wbinfo -n to properly init the domain.
Volker
r13525@SERNOX (orig r10854): jelmer | 2005-10-09 23:30:41 +0200
talloc_get_type() can return NULL..
r13526@SERNOX (orig r10855): abartlet | 2005-10-10 00:19:20 +0200
Put the domain SID in secrets.ldb by default, and add http as a
default SPN alias.
Andrew Bartlett
r13527@SERNOX (orig r10856): tridge | 2005-10-10 01:29:26 +0200
we need aclocal.m4 in ldb for standalone configure
r13530@SERNOX (orig r10859): vlendec | 2005-10-10 08:18:17 +0200
Make the flow a bit clearer
struct composite_context;
struct monitor_msg;
+struct irpc_request;
+struct rpc_request;
struct smb_composite_loadfile;
struct smb_composite_savefile;
struct nbtd_interface;
struct wins_server;
-struct wb_finddcs;
+struct nbt_dc_name;
struct wb_sid_object;
struct cldap_socket;
struct samba3;
struct wbsrv_service;
+struct wbsrv_domain;
struct wbsrv_protocol_ops;
struct wbsrv_listen_socket;
struct wbsrv_connection;
--- /dev/null
+dnl see if a declaration exists for a function or variable
+dnl defines HAVE_function_DECL if it exists
+dnl AC_HAVE_DECL(var, includes)
+AC_DEFUN(AC_HAVE_DECL,
+[
+ AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[
+ AC_TRY_COMPILE([$2],[int i = (int)$1],
+ ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)])
+ if test x"$ac_cv_have_$1_decl" = x"yes"; then
+ AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available])
+ fi
+])
--- /dev/null
+loglevel 0
+
+include tests/schema/core.schema
+include tests/schema/cosine.schema
+include tests/schema/inetorgperson.schema
+include tests/schema/openldap.schema
+include tests/schema/nis.schema
+
+
+pidfile tests/tmp/slapd.pid
+argsfile tests/tmp/slapd.args
+
+access to * by * write
+
+allow update_anon bind_anon_dn
+
+modulepath /usr/lib/ldap
+moduleload back_bdb
+
+defaultsearchbase "o=University of Michigan,c=TEST"
+
+backend bdb
+database bdb
+suffix "o=University of Michigan,c=TEST"
+directory tests/tmp/db
+index objectClass eq
+index uid eq
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ code to manipulate domain credentials
+
+ Copyright (C) Andrew Tridgell 1997-2003
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/time.h"
+#include "auth/auth.h"
+#include "lib/crypto/crypto.h"
+
+/*
+ initialise the credentials state for old-style 64 bit session keys
+
+ this call is made after the netr_ServerReqChallenge call
+*/
+static void creds_init_64bit(struct creds_CredentialState *creds,
+ const struct netr_Credential *client_challenge,
+ const struct netr_Credential *server_challenge,
+ const struct samr_Password *machine_password)
+{
+ uint32_t sum[2];
+ uint8_t sum2[8];
+
+ sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
+ sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
+
+ SIVAL(sum2,0,sum[0]);
+ SIVAL(sum2,4,sum[1]);
+
+ ZERO_STRUCT(creds->session_key);
+
+ des_crypt128(creds->session_key, sum2, machine_password->hash);
+
+ des_crypt112(creds->client.data, client_challenge->data, creds->session_key, 1);
+ des_crypt112(creds->server.data, server_challenge->data, creds->session_key, 1);
+
+ creds->seed = creds->client;
+}
+
+/*
+ initialise the credentials state for ADS-style 128 bit session keys
+
+ this call is made after the netr_ServerReqChallenge call
+*/
+static void creds_init_128bit(struct creds_CredentialState *creds,
+ const struct netr_Credential *client_challenge,
+ const struct netr_Credential *server_challenge,
+ const struct samr_Password *machine_password)
+{
+ unsigned char zero[4], tmp[16];
+ HMACMD5Context ctx;
+ struct MD5Context md5;
+
+ ZERO_STRUCT(creds->session_key);
+
+ memset(zero, 0, sizeof(zero));
+
+ hmac_md5_init_rfc2104(machine_password->hash, sizeof(machine_password->hash), &ctx);
+ MD5Init(&md5);
+ MD5Update(&md5, zero, sizeof(zero));
+ MD5Update(&md5, client_challenge->data, 8);
+ MD5Update(&md5, server_challenge->data, 8);
+ MD5Final(tmp, &md5);
+ hmac_md5_update(tmp, sizeof(tmp), &ctx);
+ hmac_md5_final(creds->session_key, &ctx);
+
+ creds->client = *client_challenge;
+ creds->server = *server_challenge;
+
+ des_crypt112(creds->client.data, client_challenge->data, creds->session_key, 1);
+ des_crypt112(creds->server.data, server_challenge->data, creds->session_key, 1);
+
+ creds->seed = creds->client;
+}
+
+
+/*
+ step the credentials to the next element in the chain, updating the
+ current client and server credentials and the seed
+*/
+static void creds_step(struct creds_CredentialState *creds)
+{
+ struct netr_Credential time_cred;
+
+ DEBUG(5,("\tseed %08x:%08x\n",
+ IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
+
+ SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
+ SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
+
+ DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
+
+ des_crypt112(creds->client.data, time_cred.data, creds->session_key, 1);
+
+ DEBUG(5,("\tCLIENT %08x:%08x\n",
+ IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
+
+ SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
+ SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
+
+ DEBUG(5,("\tseed+time+1 %08x:%08x\n",
+ IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
+
+ des_crypt112(creds->server.data, time_cred.data, creds->session_key, 1);
+
+ DEBUG(5,("\tSERVER %08x:%08x\n",
+ IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
+
+ creds->seed = time_cred;
+}
+
+
+/*
+ DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
+*/
+void creds_des_encrypt_LMKey(struct creds_CredentialState *creds, struct netr_LMSessionKey *key)
+{
+ struct netr_LMSessionKey tmp;
+ des_crypt56(tmp.key, key->key, creds->session_key, 1);
+ *key = tmp;
+}
+
+/*
+ DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
+*/
+void creds_des_decrypt_LMKey(struct creds_CredentialState *creds, struct netr_LMSessionKey *key)
+{
+ struct netr_LMSessionKey tmp;
+ des_crypt56(tmp.key, key->key, creds->session_key, 0);
+ *key = tmp;
+}
+
+/*
+ DES encrypt a 16 byte password buffer using the session key
+*/
+void creds_des_encrypt(struct creds_CredentialState *creds, struct samr_Password *pass)
+{
+ struct samr_Password tmp;
+ des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 1);
+ *pass = tmp;
+}
+
+/*
+ DES decrypt a 16 byte password buffer using the session key
+*/
+void creds_des_decrypt(struct creds_CredentialState *creds, struct samr_Password *pass)
+{
+ struct samr_Password tmp;
+ des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 0);
+ *pass = tmp;
+}
+
+/*
+ ARCFOUR encrypt/decrypt a password buffer using the session key
+*/
+void creds_arcfour_crypt(struct creds_CredentialState *creds, uint8_t *data, size_t len)
+{
+ DATA_BLOB session_key = data_blob(creds->session_key, 16);
+
+ arcfour_crypt_blob(data, len, &session_key);
+
+ data_blob_free(&session_key);
+}
+
+/*****************************************************************
+The above functions are common to the client and server interface
+next comes the client specific functions
+******************************************************************/
+
+/*
+ initialise the credentials chain and return the first client
+ credentials
+*/
+void creds_client_init(struct creds_CredentialState *creds,
+ const struct netr_Credential *client_challenge,
+ const struct netr_Credential *server_challenge,
+ const struct samr_Password *machine_password,
+ struct netr_Credential *initial_credential,
+ uint32_t negotiate_flags)
+{
+ creds->sequence = time(NULL);
+ creds->negotiate_flags = negotiate_flags;
+
+ dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
+ dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
+ dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
+
+ if (negotiate_flags & NETLOGON_NEG_128BIT) {
+ creds_init_128bit(creds, client_challenge, server_challenge, machine_password);
+ } else {
+ creds_init_64bit(creds, client_challenge, server_challenge, machine_password);
+ }
+
+ dump_data_pw("Session key", creds->session_key, 16);
+ dump_data_pw("Credential ", creds->client.data, 8);
+
+ *initial_credential = creds->client;
+}
+
+/*
+ step the credentials to the next element in the chain, updating the
+ current client and server credentials and the seed
+
+ produce the next authenticator in the sequence ready to send to
+ the server
+*/
+void creds_client_authenticator(struct creds_CredentialState *creds,
+ struct netr_Authenticator *next)
+{
+ creds->sequence += 2;
+ creds_step(creds);
+
+ next->cred = creds->client;
+ next->timestamp = creds->sequence;
+}
+
+/*
+ check that a credentials reply from a server is correct
+*/
+BOOL creds_client_check(struct creds_CredentialState *creds,
+ const struct netr_Credential *received_credentials)
+{
+ if (!received_credentials ||
+ memcmp(received_credentials->data, creds->server.data, 8) != 0) {
+ DEBUG(2,("credentials check failed\n"));
+ return False;
+ }
+ return True;
+}
+
+
+/*****************************************************************
+The above functions are common to the client and server interface
+next comes the server specific functions
+******************************************************************/
+
+/*
+ initialise the credentials chain and return the first server
+ credentials
+*/
+void creds_server_init(struct creds_CredentialState *creds,
+ const struct netr_Credential *client_challenge,
+ const struct netr_Credential *server_challenge,
+ const struct samr_Password *machine_password,
+ struct netr_Credential *initial_credential,
+ uint32_t negotiate_flags)
+{
+ if (negotiate_flags & NETLOGON_NEG_128BIT) {
+ creds_init_128bit(creds, client_challenge, server_challenge,
+ machine_password);
+ } else {
+ creds_init_64bit(creds, client_challenge, server_challenge,
+ machine_password);
+ }
+
+ *initial_credential = creds->server;
+ creds->negotiate_flags = negotiate_flags;
+}
+
+/*
+ check that a credentials reply from a server is correct
+*/
+BOOL creds_server_check(const struct creds_CredentialState *creds,
+ const struct netr_Credential *received_credentials)
+{
+ if (memcmp(received_credentials->data, creds->client.data, 8) != 0) {
+ DEBUG(2,("credentials check failed\n"));
+ dump_data_pw("client creds", creds->client.data, 8);
+ dump_data_pw("calc creds", received_credentials->data, 8);
+ return False;
+ }
+ return True;
+}
+
+NTSTATUS creds_server_step_check(struct creds_CredentialState *creds,
+ struct netr_Authenticator *received_authenticator,
+ struct netr_Authenticator *return_authenticator)
+{
+ if (!received_authenticator || !return_authenticator) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!creds) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /* TODO: this may allow the a replay attack on a non-signed
+ connection. Should we check that this is increasing? */
+ creds->sequence = received_authenticator->timestamp;
+ creds_step(creds);
+ if (creds_server_check(creds, &received_authenticator->cred)) {
+ return_authenticator->cred = creds->server;
+ return_authenticator->timestamp = creds->sequence;
+ return NT_STATUS_OK;
+ } else {
+ ZERO_STRUCTP(return_authenticator);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+}
+
+void creds_decrypt_samlogon(struct creds_CredentialState *creds,
+ uint16_t validation_level,
+ union netr_Validation *validation)
+{
+ static const char zeros[16];
+
+ struct netr_SamBaseInfo *base = NULL;
+ switch (validation_level) {
+ case 2:
+ if (validation->sam2) {
+ base = &validation->sam2->base;
+ }
+ break;
+ case 3:
+ if (validation->sam3) {
+ base = &validation->sam3->base;
+ }
+ break;
+ case 6:
+ if (validation->sam6) {
+ base = &validation->sam6->base;
+ }
+ break;
+ default:
+ /* If we can't find it, we can't very well decrypt it */
+ return;
+ }
+
+ if (!base) {
+ return;
+ }
+
+ /* find and decyrpt the session keys, return in parameters above */
+ if (validation_level == 6) {
+ /* they aren't encrypted! */
+ } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ if (memcmp(base->key.key, zeros,
+ sizeof(base->key.key)) != 0) {
+ creds_arcfour_crypt(creds,
+ base->key.key,
+ sizeof(base->key.key));
+ }
+
+ if (memcmp(base->LMSessKey.key, zeros,
+ sizeof(base->LMSessKey.key)) != 0) {
+ creds_arcfour_crypt(creds,
+ base->LMSessKey.key,
+ sizeof(base->LMSessKey.key));
+ }
+ } else {
+ if (memcmp(base->LMSessKey.key, zeros,
+ sizeof(base->LMSessKey.key)) != 0) {
+ creds_des_decrypt_LMKey(creds,
+ &base->LMSessKey);
+ }
+ }
+}
#include "lib/events/events.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
-
+#include "lib/messaging/irpc.h"
/*
block until a composite function has completed, then return the status
/* a zero timeout means immediate */
event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c);
}
+
+
+/*
+ * Some composite helpers that are handy if you write larger composite
+ * functions.
+ */
+
+BOOL comp_is_ok(struct composite_context *ctx)
+{
+ if (NT_STATUS_IS_OK(ctx->status)) {
+ return True;
+ }
+ ctx->state = COMPOSITE_STATE_ERROR;
+ if (ctx->async.fn != NULL) {
+ ctx->async.fn(ctx);
+ }
+ return False;
+}
+
+void comp_error(struct composite_context *ctx, NTSTATUS status)
+{
+ ctx->status = status;
+ SMB_ASSERT(!comp_is_ok(ctx));
+}
+
+BOOL comp_nomem(const void *p, struct composite_context *ctx)
+{
+ if (p != NULL) {
+ return False;
+ }
+ comp_error(ctx, NT_STATUS_NO_MEMORY);
+ return True;
+}
+
+void comp_done(struct composite_context *ctx)
+{
+ ctx->state = COMPOSITE_STATE_DONE;
+ if (ctx->async.fn != NULL) {
+ ctx->async.fn(ctx);
+ }
+}
+
+void comp_cont(struct composite_context *ctx,
+ struct composite_context *new_ctx,
+ void (*continuation)(struct composite_context *),
+ void *private_data)
+{
+ if (comp_nomem(new_ctx, ctx)) return;
+ new_ctx->async.fn = continuation;
+ new_ctx->async.private_data = private_data;
+}
+
+void rpc_cont(struct composite_context *ctx,
+ struct rpc_request *new_req,
+ void (*continuation)(struct rpc_request *),
+ void *private_data)
+{
+ if (comp_nomem(new_req, ctx)) return;
+ new_req->async.callback = continuation;
+ new_req->async.private = private_data;
+}
+
+void irpc_cont(struct composite_context *ctx,
+ struct irpc_request *new_req,
+ void (*continuation)(struct irpc_request *),
+ void *private_data)
+{
+ if (comp_nomem(new_req, ctx)) return;
+ new_req->async.fn = continuation;
+ new_req->async.private = private_data;
+}
+
/*
pull a nbt name, WINS Replication uses another on wire format for nbt name
*/
-NTSTATUS ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r)
+NTSTATUS ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name **_r)
{
struct nbt_name *r;
uint8_t *namebuf;
return req->status;
}
+static void wrepl_request_trigger(struct wrepl_request *req);
/*
connect a wrepl_socket to a WINS server
status = socket_connect(wrepl_socket->sock, our_ip, 0, peer_ip,
WINS_REPLICATION_PORT, 0);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) goto failed;
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ req->wrepl_socket = wrepl_socket;
+ req->state = WREPL_REQUEST_ERROR;
+ req->status = status;
+ wrepl_request_trigger(req);
+ return req;
+ }
return req;
--- /dev/null
+/*
+ dfs interface definition
+*/
+
+#include "idl_types.h"
+
+[ uuid("4fc742e0-4a10-11cf-8273-00aa004ae673"),
+ version(3.0),
+ pointer_default(unique),
+ helpstring("Settings for Microsoft Distributed File System")
+] interface netdfs
+{
+ /******************/
+ /* Function: 0x00 */
+ void dfs_GetManagerVersion(
+ [out] uint32 *exist_flag
+ );
+
+
+ /******************/
+ /* Function: 0x01 */
+ WERROR dfs_Add (
+ [in] unistr *path,
+ [in] unistr *server,
+ [in,unique] unistr *share,
+ [in,unique] unistr *comment,
+ [in] uint32 flags
+ );
+
+ /******************/
+ /* Function: 0x02 */
+ WERROR dfs_Remove (
+ [in] unistr *path,
+ [in,unique] unistr *server,
+ [in,unique] unistr *share
+ );
+
+ /******************/
+ /* Function: 0x03 */
+ WERROR dfs_SetInfo ();
+
+ /******************/
+ /* Function: 0x04 */
+
+ typedef struct {
+ } dfs_Info0;
+
+ typedef struct {
+ unistr *path;
+ } dfs_Info1;
+
+ typedef struct {
+ unistr *path;
+ unistr *comment;
+ uint32 state;
+ uint32 num_stores;
+ } dfs_Info2;
+
+ typedef struct {
+ uint32 state;
+ unistr *server;
+ unistr *share;
+ } dfs_StorageInfo;
+
+ typedef struct {
+ unistr *path;
+ unistr *comment;
+ uint32 state;
+ uint32 num_stores;
+ [size_is(num_stores)] dfs_StorageInfo *stores;
+ } dfs_Info3;
+
+ typedef struct {
+ unistr *path;
+ unistr *comment;
+ uint32 state;
+ uint32 timeout;
+ GUID guid;
+ uint32 num_stores;
+ [size_is(num_stores)] dfs_StorageInfo *stores;
+ } dfs_Info4;
+
+ typedef struct {
+ unistr *comment;
+ } dfs_Info100;
+
+ typedef struct {
+ uint32 state;
+ } dfs_Info101;
+
+ typedef struct {
+ uint32 timeout;
+ } dfs_Info102;
+
+ typedef struct {
+ unistr *dom_root;
+ } dfs_Info200;
+
+ typedef struct {
+ uint32 flags;
+ unistr *dom_root;
+ } dfs_Info300;
+
+ typedef union {
+ [case(0)] dfs_Info0 *info0;
+ [case(1)] dfs_Info1 *info1;
+ [case(2)] dfs_Info2 *info2;
+ [case(3)] dfs_Info3 *info3;
+ [case(4)] dfs_Info4 *info4;
+ [case(100)] dfs_Info100 *info100;
+ [case(101)] dfs_Info101 *info101;
+ [case(102)] dfs_Info102 *info102;
+ } dfs_Info;
+
+ WERROR dfs_GetInfo (
+ [in] unistr *path,
+ [in,unique] unistr *server,
+ [in,unique] unistr *share,
+ [in] uint32 level,
+ [out,switch_is(level)] dfs_Info *info
+ );
+
+ /******************/
+ /* Function: 0x05 */
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info1 *s;
+ } dfs_EnumArray1;
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info2 *s;
+ } dfs_EnumArray2;
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info3 *s;
+ } dfs_EnumArray3;
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info4 *s;
+ } dfs_EnumArray4;
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info200 *s;
+ } dfs_EnumArray200;
+
+ typedef struct {
+ uint32 count;
+ [size_is(count)] dfs_Info300 *s;
+ } dfs_EnumArray300;
+
+
+ typedef union {
+ [case(1)] dfs_EnumArray1 *info1;
+ [case(2)] dfs_EnumArray2 *info2;
+ [case(3)] dfs_EnumArray3 *info3;
+ [case(4)] dfs_EnumArray4 *info4;
+ [case(200)] dfs_EnumArray200 *info200;
+ [case(300)] dfs_EnumArray300 *info300;
+ } dfs_EnumInfo;
+
+ typedef struct {
+ uint32 level;
+ [switch_is(level)] dfs_EnumInfo e;
+ } dfs_EnumStruct;
+
+ WERROR dfs_Enum (
+ [in] uint32 level,
+ [in] uint32 bufsize,
+ [in,out,unique] dfs_EnumStruct *info,
+ [in,unique] uint32 *unknown,
+ [in,out,unique] uint32 *total
+ );
+
+ /* Function 0x06 */
+ WERROR dfs_Rename();
+
+ /* Function 0x07 */
+ WERROR dfs_Move();
+
+ /* Function 0x08 */
+ WERROR dfs_ManagerGetConfigInfo();
+
+ /* Function 0x09 */
+ WERROR dfs_ManagerSendSiteInfo();
+
+ /* Function 0x0a */
+ WERROR dfs_AddFtRoot();
+
+ /* Function 0x0b */
+ WERROR dfs_RemoveFtRoot();
+
+ /* Function 0x0c */
+ WERROR dfs_AddStdRoot();
+
+ /* Function 0x0d */
+ WERROR dfs_RemoveStdRoot();
+
+ /* Function 0x0e */
+ WERROR dfs_ManagerInitialize();
+
+ /* Function 0x0f */
+ WERROR dfs_AddStdRootForced();
+
+ /* Function 0x10 */
+ WERROR dfs_GetDcAddress();
+
+ /* Function 0x11 */
+ WERROR dfs_SetDcAddress();
+
+ /* Function 0x12 */
+ WERROR dfs_FlushFtTable();
+
+ /* Function 0x13 */
+ WERROR dfs_Add2();
+
+ /* Function 0x14 */
+ WERROR dfs_Remove2();
+
+ /* Function 0x15 */
+ WERROR dfs_EnumEx();
+
+ /* Function 0x16 */
+ WERROR dfs_SetInfo2();
+}
pid_t pid; /* pid of calling process */
uint32_t flags; /* flags relavant to a given request */
winbind_string domain_name; /* name of domain for which the request applies */
- int msgid;
union {
winbind_string winsreq; /* WINS request */
winbind_string cache_key;
} dual_sidaliases;
} data;
+ char *extra_data;
+ size_t extra_len;
char null_term;
};
status = dcerpc_ndr_request_recv(req);
- if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
+ if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
NDR_PRINT_OUT_DEBUG($name, r);
}
";
my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
- if ($l->{TYPE} eq "ARRAY" and ($l->{IS_CONFORMANT} or $l->{IS_VARYING}
- or is_charset_array($e, $l))) {
+ if ($l->{TYPE} eq "ARRAY" and ($l->{IS_CONFORMANT} or $l->{IS_VARYING})) {
$var_name = get_pointer_to($var_name);
}
} elsif ($l->{TYPE} eq "ARRAY") {
my $length;
- if ($l->{IS_CONFORMANT} or $l->{IS_VARYING} or
- is_charset_array($e,$l)) {
+ if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {
$var_name = get_pointer_to($var_name);
}
my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);
- if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT}
- or is_charset_array($e,$l))) {
+ if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) {
$var_name = get_pointer_to($var_name);
}
pidl "/* Return variables */";
foreach my $e (@{$fn->{ELEMENTS}}) {
next unless (grep(/out/, @{$e->{DIRECTION}}));
-
+
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER") {
warning($e->{ORIGINAL}, "First element not a pointer for [out] argument");
next;
}
+
CopyLevel($e, $e->{LEVELS}[1], $e->{NAME}, "r.$e->{NAME}");
}
{
my ($if,$u,$n) = @_;
- my $extra = {};
-
- $extra->{switch_value} = $u->{SWITCH_TYPE};
+ my $extra = {
+ switch_value => $u->{SWITCH_TYPE}
+ };
+
+ if (not defined($extra->{switch_value})) {
+ $extra->{switch_value} = "uint32";
+ }
foreach my $e (@{$u->{ELEMENTS}}) {
foreach my $l (@{$e->{LEVELS}}) {
{
my ($e,$l,$nl,$env,$varname,$what,$align) = @_;
- my @args = ($e,$l,$varname,$what,$align);
-
- # See if we need to add a level argument because we're parsing a union
- foreach (@{$e->{LEVELS}}) {
- next unless ($_->{TYPE} eq "SWITCH");
- my $t = getType($l->{DATA_TYPE});
-
- # Set 0 here because one of the variables referenced in SWITCH_IS
- # might be an in variable while this one is [out]
- if (grep(/in/, @{$e->{DIRECTION}}) or
- not defined($t) or
- has_property($t->{DATA}, "nodiscriminant")) {
- push (@args, ParseExpr($_->{SWITCH_IS}, $env));
- } else {
- push (@args, -1);
- }
- }
-
- my $c = DissectType(@args);
+ my $c = DissectType($e,$l,$varname,$what,$align);
return if not $c;
if (defined($e->{ALIGN})) {
pidl InitType($e, $l, ParseExpr($e->{NAME}, $env), $varname);
} elsif ($l->{TYPE} eq "SWITCH") {
InitLevel($e, GetNextLevel($e,$l), $varname, $env);
+ pidl ParseExpr($e->{NAME}, $env) . ".switch_value = " . ParseExpr($l->{SWITCH_IS}, $env) . ";";
}
}
my $pfn = "$fn\_p";
my $dfn = "$fn\_d";
- pidl "BOOL $pfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
+ pidl "BOOL $pfn(const char *desc, $sn* v, prs_struct *ps, int depth)";
pidl "{";
indent;
DeclareArrayVariables($u->{ELEMENTS});
if (defined ($u->{SWITCH_TYPE})) {
- pidl "if (MARSHALLING(ps)) ";
- pidl "\tv->switch_value = level;";
- pidl "";
pidl "if (!prs_$u->{SWITCH_TYPE}(\"switch_value\", ps, depth, &v->switch_value))";
pidl "\treturn False;";
pidl "";
- } else {
- pidl "v->switch_value = level;";
}
# Maybe check here that level and v->switch_value are equal?
pidl "}";
pidl "";
- pidl "BOOL $dfn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
+ pidl "BOOL $dfn(const char *desc, $sn* v, prs_struct *ps, int depth)";
pidl "{";
indent;
DeclareArrayVariables($u->{ELEMENTS});
}
-sub CreateFnDirection($$$$)
+sub CreateFnDirection($$$$$)
{
- my ($fn,$ifn, $s,$es) = @_;
+ my ($fn,$ifn,$s,$all,$es) = @_;
my $args = "";
- foreach (@$es) {
- $args .= ", " . DeclLong($_);
- }
+ foreach (@$all) { $args .= ", " . DeclLong($_); }
- my $env = { "this" => "v" };
+ my $env = { };
GenerateEnvElement($_, $env) foreach (@$es);
pidl "BOOL $ifn($s *v$args)";
my @in = ();
my @out = ();
+ my @all = @{$fn->{ELEMENTS}};
foreach (@{$fn->{ELEMENTS}}) {
push (@in, $_) if (grep(/in/, @{$_->{DIRECTION}}));
}
if (defined($fn->{RETURN_TYPE})) {
- push (@out, {
+ my $status = {
NAME => "status",
TYPE => $fn->{RETURN_TYPE},
LEVELS => [
DATA_TYPE => $fn->{RETURN_TYPE}
}
]
- } );
+ };
+
+ push (@out, $status);
+ push (@all, $status);
}
CreateFnDirection("$if->{NAME}_io_q_$fn->{NAME}",
"init_$if->{NAME}_q_$fn->{NAME}",
uc("$if->{NAME}_q_$fn->{NAME}"),
- \@in);
+ \@in, \@in);
CreateFnDirection("$if->{NAME}_io_r_$fn->{NAME}",
"init_$if->{NAME}_r_$fn->{NAME}",
uc("$if->{NAME}_r_$fn->{NAME}"),
- \@out);
+ \@all, \@out);
}
sub ParseInterface($)
$known_types->{$t} = $d;
}
-sub GetType($)
-{
- my $e = shift;
-
-}
-
# Return type without special stuff, as used in
# declarations for internal structs
sub DeclShort($)
}
}
-sub DissectType
+sub DissectType($$$$$)
{
- my @args = @_;
- my $e = shift @_;
- my $l = shift @_;
- my $varname = shift @_;
- my $what = shift @_;
- my $align = shift @_;
+ my ($e,$l,$varname,$what,$align) = @_;
my $t = $known_types->{$l->{DATA_TYPE}};
# DISSECT can be a function
if (ref($dissect) eq "CODE") {
- return $dissect->(@args);
+ return $dissect->($e,$l,$varname,$what,$align);
} else {
return $dissect;
}
my $dissect_p;
if ($td->{DATA}->{TYPE} eq "UNION") {
$decl.="_CTR";
- $dissect_p = sub {
- my ($e,$l,$n,$w,$a,$s) = @_;
-
- return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, $s, ps, depth)";
- };
+ }
- $dissect_d = sub {
- my ($e,$l,$n,$w,$a,$s) = @_;
+ $dissect_p = sub {
+ my ($e,$l,$n,$w,$a) = @_;
- return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, $s, ps, depth)";
- };
-
- } else {
- $dissect_p = sub {
- my ($e,$l,$n,$w,$a) = @_;
-
- return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, ps, depth)";
- };
- $dissect_d = sub {
- my ($e,$l,$n,$w,$a) = @_;
-
- return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, ps, depth)";
- };
+ return "$if->{NAME}_io_$td->{NAME}_p(\"$e->{NAME}\", &$n, ps, depth)";
+ };
+ $dissect_d = sub {
+ my ($e,$l,$n,$w,$a) = @_;
- }
+ return "$if->{NAME}_io_$td->{NAME}_d(\"$e->{NAME}\", &$n, ps, depth)";
+ };
AddType($td->{NAME}, {
DECL => $decl,
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ endpoint server for the spoolss pipe
+
+ Copyright (C) Tim Potter 2004
+ Copyright (C) Stefan Metzmacher 2005
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "rpc_server/dcerpc_server.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "rpc_server/common/common.h"
+#include "ntptr/ntptr.h"
+#include "lib/socket/socket.h"
+#include "smbd/service_stream.h"
+
+#define SPOOLSS_BUFFER_UNION(fn,info,level) \
+ ((info)?ndr_size_##fn(info, level, 0):0)
+
+#define SPOOLSS_BUFFER_UNION_ARRAY(fn,info,level,count) \
+ ((info)?ndr_size_##fn##_info(dce_call, level, count, info):0)
+
+#define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= r->out.needed)?val_true:val_false)
+
+static WERROR spoolss_parse_printer_name(TALLOC_CTX *mem_ctx, const char *name,
+ const char **_server_name,
+ const char **_object_name,
+ enum ntptr_HandleType *_object_type)
+{
+ char *p;
+ char *server = NULL;
+ char *server_unc = NULL;
+ const char *object = name;
+
+ /* no printername is there it's like open server */
+ if (!name) {
+ *_server_name = NULL;
+ *_object_name = NULL;
+ *_object_type = NTPTR_HANDLE_SERVER;
+ return WERR_OK;
+ }
+
+ /* just "\\" is invalid */
+ if (strequal("\\\\", name)) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ if (strncmp("\\\\", name, 2) == 0) {
+ server_unc = talloc_strdup(mem_ctx, name);
+ W_ERROR_HAVE_NO_MEMORY(server_unc);
+ server = server_unc + 2;
+
+ /* here we know we have "\\" in front not followed
+ * by '\0', now see if we have another "\" in the string
+ */
+ p = strchr_m(server, '\\');
+ if (!p) {
+ /* there's no other "\", so it's ("\\%s",server)
+ */
+ *_server_name = server_unc;
+ *_object_name = NULL;
+ *_object_type = NTPTR_HANDLE_SERVER;
+ return WERR_OK;
+ }
+ /* here we know that we have ("\\%s\",server),
+ * if we have '\0' as next then it's an invalid name
+ * otherwise the printer_name
+ */
+ p[0] = '\0';
+ /* everything that follows is the printer name */
+ p++;
+ object = p;
+
+ /* just "" as server is invalid */
+ if (strequal(server, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+ }
+
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+#define XCV_PORT ",XcvPort "
+#define XCV_MONITOR ",XcvMonitor "
+ if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) {
+ object += strlen(XCV_PORT);
+
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_PORT;
+ return WERR_OK;
+ } else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) {
+ object += strlen(XCV_MONITOR);
+
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_MONITOR;
+ return WERR_OK;
+ }
+
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_PRINTER;
+ return WERR_OK;
+}
+
+/*
+ * Check server_name is:
+ * - "" , functions that don't allow "",
+ * should check that on their own, before calling this function
+ * - our name (only netbios yet, TODO: need to test dns name!)
+ * - our ip address of the current use socket
+ * otherwise return WERR_INVALID_PRINTER_NAME
+ */
+static WERROR spoolss_check_server_name(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ const char *server_name)
+{
+ BOOL ret;
+ char *str;
+
+ /* NULL is ok */
+ if (!server_name) return WERR_OK;
+
+ /* "" is ok */
+ ret = strequal("",server_name);
+ if (ret) return WERR_OK;
+
+ /* just "\\" is invalid */
+ if (strequal("\\\\", server_name)) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ /* then we need "\\" */
+ if (strncmp("\\\\", server_name, 2) != 0) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+
+ server_name += 2;
+
+ /* NETBIOS NAME is ok */
+ ret = strequal(lp_netbios_name(), server_name);
+ if (ret) return WERR_OK;
+
+ /* DNS NAME is ok
+ * TODO: we need to check if aliases are also ok
+ */
+ if (lp_realm()) {
+ str = talloc_asprintf(mem_ctx, "%s.%s",
+ lp_netbios_name(),
+ lp_realm());
+ W_ERROR_HAVE_NO_MEMORY(str);
+
+ ret = strequal(str, server_name);
+ talloc_free(str);
+ if (ret) return WERR_OK;
+ }
+
+ str = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx);
+ W_ERROR_HAVE_NO_MEMORY(str);
+
+ ret = strequal(str, server_name);
+ talloc_free(str);
+ if (ret) return WERR_OK;
+
+ return WERR_INVALID_PRINTER_NAME;
+}
+
+static NTSTATUS dcerpc_spoolss_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+ NTSTATUS status;
+ struct ntptr_context *ntptr;
+
+ status = ntptr_init_context(dce_call->context, lp_ntptr_providor(), &ntptr);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ dce_call->context->private = ntptr;
+
+ return NT_STATUS_OK;
+}
+
+#define DCESRV_INTERFACE_SPOOLSS_BIND dcerpc_spoolss_bind
+
+/*
+ spoolss_EnumPrinters
+*/
+static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinters *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPrinters(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_OpenPrinterEx *r);
+/*
+ spoolss_OpenPrinter
+*/
+static WERROR spoolss_OpenPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_OpenPrinter *r)
+{
+ WERROR status;
+ struct spoolss_OpenPrinterEx *r2;
+
+ r2 = talloc(mem_ctx, struct spoolss_OpenPrinterEx);
+ W_ERROR_HAVE_NO_MEMORY(r2);
+
+ r2->in.printername = r->in.printername;
+ r2->in.datatype = r->in.datatype;
+ r2->in.devmode_ctr = r->in.devmode_ctr;
+ r2->in.access_mask = r->in.access_mask;
+ r2->in.level = 1;
+ r2->in.userlevel.level1 = NULL;
+
+ r2->out.handle = r->out.handle;
+
+ /* TODO: we should take care about async replies here,
+ if spoolss_OpenPrinterEx() would be async!
+ */
+ status = spoolss_OpenPrinterEx(dce_call, mem_ctx, r2);
+
+ r->out.handle = r2->out.handle;
+
+ return status;
+}
+
+
+/*
+ spoolss_SetJob
+*/
+static WERROR spoolss_SetJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SetJob *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetJob
+*/
+static WERROR spoolss_GetJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetJob *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumJobs
+*/
+static WERROR spoolss_EnumJobs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumJobs *r)
+{
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_AddPrinter
+*/
+static WERROR spoolss_AddPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinter
+*/
+static WERROR spoolss_DeletePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_SetPrinter
+*/
+static WERROR spoolss_SetPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SetPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetPrinter
+*/
+static WERROR spoolss_GetPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPrinterDriver
+*/
+static WERROR spoolss_AddPrinterDriver(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrinterDriver *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrinterDrivers
+*/
+static WERROR spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinterDrivers *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPrinterDrivers(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_GetPrinterDriver
+*/
+static WERROR spoolss_GetPrinterDriver(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinterDriver *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetPrinterDriverDirectory
+*/
+static WERROR spoolss_GetPrinterDriverDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinterDriverDirectory *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_GetPrinterDriverDirectory(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, r->out.info, r->in.level);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_DeletePrinterDriver
+*/
+static WERROR spoolss_DeletePrinterDriver(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterDriver *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPrintProcessor
+*/
+static WERROR spoolss_AddPrintProcessor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrintProcessor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrintProcessors
+*/
+static WERROR spoolss_EnumPrintProcessors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrintProcessors *r)
+{
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_GetPrintProcessorDirectory
+*/
+static WERROR spoolss_GetPrintProcessorDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrintProcessorDirectory *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_StartDocPrinter
+*/
+static WERROR spoolss_StartDocPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_StartDocPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_StartPagePrinter
+*/
+static WERROR spoolss_StartPagePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_StartPagePrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_WritePrinter
+*/
+static WERROR spoolss_WritePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_WritePrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EndPagePrinter
+*/
+static WERROR spoolss_EndPagePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EndPagePrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AbortPrinter
+*/
+static WERROR spoolss_AbortPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AbortPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ReadPrinter
+*/
+static WERROR spoolss_ReadPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ReadPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EndDocPrinter
+*/
+static WERROR spoolss_EndDocPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EndDocPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddJob
+*/
+static WERROR spoolss_AddJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddJob *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ScheduleJob
+*/
+static WERROR spoolss_ScheduleJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ScheduleJob *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetPrinterData
+*/
+static WERROR spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinterData *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_GetPrintServerData(handle, mem_ctx, r);
+ break;
+ default:
+ status = WERR_FOOBAR;
+ break;
+ }
+
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = ndr_size_spoolss_PrinterData(&r->out.data, r->out.type, 0);
+ r->out.type = SPOOLSS_BUFFER_OK(r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL);
+ r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
+}
+
+
+/*
+ spoolss_SetPrinterData
+*/
+static WERROR spoolss_SetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SetPrinterData *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_WaitForPrinterChange
+*/
+static WERROR spoolss_WaitForPrinterChange(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_WaitForPrinterChange *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ClosePrinter
+*/
+static WERROR spoolss_ClosePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ClosePrinter *r)
+{
+ struct dcesrv_handle *h;
+
+ *r->out.handle = *r->in.handle;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+
+ talloc_free(h);
+
+ ZERO_STRUCTP(r->out.handle);
+
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_AddForm
+*/
+static WERROR spoolss_AddForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddForm *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_AddPrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_AddPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_DeleteForm
+*/
+static WERROR spoolss_DeleteForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeleteForm *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_DeletePrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_DeletePrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_GetForm
+*/
+static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetForm *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ /*
+ * stupid, but w2k3 returns WERR_BADFID here?
+ */
+ return WERR_BADFID;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_GetPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, r->out.info, r->in.level);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_SetForm
+*/
+static WERROR spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SetForm *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_SetPrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_SetPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_EnumForms
+*/
+static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumForms *r)
+{
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+ if (!handle)
+ return WERR_BADFID;
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_EnumPrintServerForms(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_EnumPrinterForms(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_EnumPorts
+*/
+static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPorts *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPorts(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_EnumMonitors
+*/
+static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumMonitors *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumMonitors(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+}
+
+
+/*
+ spoolss_AddPort
+*/
+static WERROR spoolss_AddPort(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPort *r)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+
+/*
+ spoolss_ConfigurePort
+*/
+static WERROR spoolss_ConfigurePort(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ConfigurePort *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePort
+*/
+static WERROR spoolss_DeletePort(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePort *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_CreatePrinterIC
+*/
+static WERROR spoolss_CreatePrinterIC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_CreatePrinterIC *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_PlayGDIScriptOnPrinterIC
+*/
+static WERROR spoolss_PlayGDIScriptOnPrinterIC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_PlayGDIScriptOnPrinterIC *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterIC
+*/
+static WERROR spoolss_DeletePrinterIC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterIC *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPrinterConnection
+*/
+static WERROR spoolss_AddPrinterConnection(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrinterConnection *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterConnection
+*/
+static WERROR spoolss_DeletePrinterConnection(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterConnection *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_PrinterMessageBox
+*/
+static WERROR spoolss_PrinterMessageBox(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_PrinterMessageBox *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddMonitor
+*/
+static WERROR spoolss_AddMonitor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddMonitor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeleteMonitor
+*/
+static WERROR spoolss_DeleteMonitor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeleteMonitor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrintProcessor
+*/
+static WERROR spoolss_DeletePrintProcessor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrintProcessor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPrintProvidor
+*/
+static WERROR spoolss_AddPrintProvidor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrintProvidor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrintProvidor
+*/
+static WERROR spoolss_DeletePrintProvidor(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrintProvidor *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrintProcDataTypes
+*/
+static WERROR spoolss_EnumPrintProcDataTypes(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrintProcDataTypes *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ResetPrinter
+*/
+static WERROR spoolss_ResetPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ResetPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetPrinterDriver2
+*/
+static WERROR spoolss_GetPrinterDriver2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinterDriver2 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_FindFirstPrinterChangeNotification
+*/
+static WERROR spoolss_FindFirstPrinterChangeNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_FindFirstPrinterChangeNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_FindNextPrinterChangeNotification
+*/
+static WERROR spoolss_FindNextPrinterChangeNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_FindNextPrinterChangeNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_FindClosePrinterNotify
+*/
+static WERROR spoolss_FindClosePrinterNotify(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_FindClosePrinterNotify *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_RouterFindFirstPrinterChangeNotificationOld
+*/
+static WERROR spoolss_RouterFindFirstPrinterChangeNotificationOld(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ReplyOpenPrinter
+*/
+static WERROR spoolss_ReplyOpenPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ReplyOpenPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_RouterReplyPrinter
+*/
+static WERROR spoolss_RouterReplyPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterReplyPrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ReplyClosePrinter
+*/
+static WERROR spoolss_ReplyClosePrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ReplyClosePrinter *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPortEx
+*/
+static WERROR spoolss_AddPortEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPortEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_RouterFindFirstPrinterChangeNotification
+*/
+static WERROR spoolss_RouterFindFirstPrinterChangeNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterFindFirstPrinterChangeNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_SpoolerInit
+*/
+static WERROR spoolss_SpoolerInit(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SpoolerInit *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_ResetPrinterEx
+*/
+static WERROR spoolss_ResetPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_ResetPrinterEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_RemoteFindFirstPrinterChangeNotifyEx
+*/
+static WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
+{
+ /*
+ * TODO: for now just return ok,
+ * to keep the w2k3 PrintServer
+ * happy to allow to open the Add Printer GUI
+ */
+ return WERR_OK;
+}
+
+
+/*
+ spoolss_RouterRefreshPrinterChangeNotification
+*/
+static WERROR spoolss_RouterRefreshPrinterChangeNotification(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RouterRefreshPrinterChangeNotification *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_RemoteFindNextPrinterChangeNotifyEx
+*/
+static WERROR spoolss_RemoteFindNextPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_RemoteFindNextPrinterChangeNotifyEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_44
+*/
+static WERROR spoolss_44(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_44 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ spoolss_OpenPrinterEx
+*/
+static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_OpenPrinterEx *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ const char *server;
+ const char *object;
+ enum ntptr_HandleType type;
+ WERROR status;
+
+ ZERO_STRUCTP(r->out.handle);
+
+ status = spoolss_parse_printer_name(mem_ctx, r->in.printername, &server, &object, &type);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ switch (type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_OpenPrintServer(ntptr, mem_ctx, r, server, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PORT:
+ status = ntptr_OpenPort(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_MONITOR:
+ status = ntptr_OpenMonitor(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_OpenPrinter(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ h = dcesrv_handle_new(dce_call->context, handle->type);
+ W_ERROR_HAVE_NO_MEMORY(h);
+
+ h->data = talloc_steal(h, handle);
+
+ *r->out.handle = h->wire_handle;
+
+ return WERR_OK;
+}
+
+/*
+ spoolss_AddPrinterEx
+*/
+static WERROR spoolss_AddPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrinterEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_47
+*/
+static WERROR spoolss_47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_47 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrinterData
+*/
+static WERROR spoolss_EnumPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinterData *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterData
+*/
+static WERROR spoolss_DeletePrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterData *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_4a
+*/
+static WERROR spoolss_4a(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_4a *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_4b
+*/
+static WERROR spoolss_4b(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_4b *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_4c
+*/
+static WERROR spoolss_4c(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_4c *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_SetPrinterDataEx
+*/
+static WERROR spoolss_SetPrinterDataEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_SetPrinterDataEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_GetPrinterDataEx
+*/
+static WERROR spoolss_GetPrinterDataEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_GetPrinterDataEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrinterDataEx
+*/
+static WERROR spoolss_EnumPrinterDataEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinterDataEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_EnumPrinterKey
+*/
+static WERROR spoolss_EnumPrinterKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinterKey *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterDataEx
+*/
+static WERROR spoolss_DeletePrinterDataEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterDataEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterKey
+*/
+static WERROR spoolss_DeletePrinterKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterKey *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_53
+*/
+static WERROR spoolss_53(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_53 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_DeletePrinterDriverEx
+*/
+static WERROR spoolss_DeletePrinterDriverEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_DeletePrinterDriverEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_55
+*/
+static WERROR spoolss_55(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_55 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_56
+*/
+static WERROR spoolss_56(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_56 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_57
+*/
+static WERROR spoolss_57(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_57 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_58
+*/
+static WERROR spoolss_58(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_58 *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_AddPrinterDriverEx
+*/
+static WERROR spoolss_AddPrinterDriverEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_AddPrinterDriverEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5a
+*/
+static WERROR spoolss_5a(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5a *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5b
+*/
+static WERROR spoolss_5b(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5b *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5c
+*/
+static WERROR spoolss_5c(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5c *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5d
+*/
+static WERROR spoolss_5d(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5d *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5e
+*/
+static WERROR spoolss_5e(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5e *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ spoolss_5f
+*/
+static WERROR spoolss_5f(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_5f *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* include the generated boilerplate */
+#include "librpc/gen_ndr/ndr_spoolss_s.c"
--- /dev/null
+###############################
+# Domain Naming Context
+###############################
+dn: ${BASEDN}
+objectClass: top
+objectClass: domain
+objectClass: domainDNS
+dnsDomain: ${DNSDOMAIN}
+dc: ${RDN_DC}
+objectGUID: ${DOMAINGUID}
+creationTime: ${NTTIME}
+forceLogoff: 0x8000000000000000
+lockoutDuration: -18000000000
+lockOutObservationWindow: -18000000000
+lockoutThreshold: 0
+uSNCreated: 1
+uSNChanged: 1
+maxPwdAge: -37108517437440
+minPwdAge: 0
+minPwdLength: 7
+modifiedCountAtLastProm: 0
+nextRid: 1001
+pwdProperties: 1
+pwdHistoryLength: 24
+objectSid: ${DOMAINSID}
+oEMInformation: Provisioned by Samba4: ${LDAPTIME}
+serverState: 1
+nTMixedDomain: 1
+msDS-Behavior-Version: 0
+ridManagerReference: CN=RID Manager$,CN=System,${BASEDN}
+uASCompat: 1
+modifiedCount: 1
+objectCategory: CN=Domain-DNS,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+subRefs: CN=Configuration,${BASEDN}
+subRefs: CN=Schema,CN=Configuration,${BASEDN}
+canonicalName: ${REALM}/
+
+dn: CN=Users,${BASEDN}
+objectClass: top
+objectClass: container
+cn: Users
+description: Default container for upgraded user accounts
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: FALSE
+systemFlags: 0x8c000000
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+dn: CN=Computers,${BASEDN}
+objectClass: top
+objectClass: container
+cn: Computers
+description: Default container for upgraded computer accounts
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: FALSE
+systemFlags: 0x8c000000
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+dn: OU=Domain Controllers,${BASEDN}
+objectClass: top
+objectClass: organizationalUnit
+ou: Domain Controllers
+description: Default container for domain controllers
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: FALSE
+systemFlags: 0x8c000000
+objectCategory: CN=Organizational-Unit,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+dn: CN=ForeignSecurityPrincipals,${BASEDN}
+objectClass: top
+objectClass: container
+cn: ForeignSecurityPrincipals
+description: Default container for security identifiers (SIDs) associated with objects from external, trusted domains
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: FALSE
+systemFlags: 0x8c000000
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+dn: CN=System,${BASEDN}
+objectClass: top
+objectClass: container
+cn: System
+description: Builtin system settings
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x8c000000
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+dn: CN=RID Manager$,CN=System,${BASEDN}
+objectclass: top
+objectclass: rIDManager
+cn: RID Manager$
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x8c000000
+objectCategory: CN=RID-Manager,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+fSMORoleOwner: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+rIDAvailablePool: 4611686014132423217
+
+dn: CN=DomainUpdates,CN=System,${BASEDN}
+objectClass: top
+objectClass: container
+cn: DomainUpdates
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=Windows2003Update,CN=DomainUpdates,CN=System,${BASEDN}
+objectClass: top
+objectClass: container
+cn: Windows2003Update
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+revision: 8
+
+dn: CN=Infrastructure,${BASEDN}
+objectclass: top
+objectclass: infrastructureUpdate
+cn: Infrastructure
+instanceType: 4
+uSNCreated: 1
+uSNChanged: 1
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x8c000000
+objectCategory: CN=Infrastructure-Update,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+fSMORoleOwner: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+
+dn: CN=Builtin,${BASEDN}
+objectClass: top
+objectClass: builtinDomain
+cn: Builtin
+instanceType: 4
+showInAdvancedViewOnly: FALSE
+forceLogoff: 0x8000000000000000
+lockoutDuration: -18000000000
+lockOutObservationWindow: -18000000000
+lockoutThreshold: 0
+maxPwdAge: -37108517437440
+minPwdAge: 0
+minPwdLength: 0
+modifiedCountAtLastProm: 0
+nextRid: 1000
+pwdProperties: 0
+pwdHistoryLength: 0
+objectSid: S-1-5-32
+serverState: 1
+uASCompat: 1
+modifiedCount: 1
+objectCategory: CN=Builtin-Domain,CN=Schema,CN=Configuration,${BASEDN}
+isCriticalSystemObject: TRUE
+
+###############################
+# Configuration Naming Context
+###############################
+dn: CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: configuration
+cn: Configuration
+instanceType: 13
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=Configuration,CN=Schema,CN=Configuration,${BASEDN}
+subRefs: CN=Schema,CN=Configuration,${BASEDN}
+masteredBy: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+msDs-masteredBy: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+
+dn: CN=Partitions,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: crossRefContainer
+cn: Partitions
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x80000000
+objectCategory: CN=Cross-Ref-Container,CN=Schema,CN=Configuration,${BASEDN}
+msDS-Behavior-Version: 0
+fSMORoleOwner: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+
+dn: CN=Enterprise Configuration,CN=Partitions,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: crossRef
+cn: Enterprise Configuration
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x00000001
+objectCategory: CN=Cross-Ref,CN=Schema,CN=Configuration,${BASEDN}
+nCName: CN=Configuration,${BASEDN}
+dnsRoot: ${DNSDOMAIN}
+
+dn: CN=Enterprise Schema,CN=Partitions,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: crossRef
+cn: Enterprise Schema
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x00000001
+objectCategory: CN=Cross-Ref,CN=Schema,CN=Configuration,${BASEDN}
+nCName: CN=Schema,CN=Configuration,${BASEDN}
+dnsRoot: ${DNSDOMAIN}
+
+dn: CN=${DOMAIN},CN=Partitions,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: crossRef
+cn: ${DOMAIN}
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x00000003
+objectCategory: CN=Cross-Ref,CN=Schema,CN=Configuration,${BASEDN}
+nCName: ${BASEDN}
+nETBIOSName: ${DOMAIN}
+dnsRoot: ${DNSDOMAIN}
+
+dn: CN=Sites,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: sitesContainer
+cn: Sites
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x82000000
+objectCategory: CN=Sites-Container,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: site
+cn: ${DEFAULTSITE}
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x82000000
+objectCategory: CN=Site,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: serversContainer
+cn: Servers
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x82000000
+objectCategory: CN=Servers-Container,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: server
+cn: ${NETBIOSNAME}
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x52000000
+objectCategory: CN=Server,CN=Schema,CN=Configuration,${BASEDN}
+dNSHostName: ${DNSNAME}
+serverReference: CN=${NETBIOSNAME},OU=Domain Controllers,${BASEDN}
+
+dn: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: applicationSettings
+objectClass: nTDSDSA
+cn: NTDS Settings
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x02000000
+objectCategory: CN=NTDS-DSA,CN=Schema,CN=Configuration,${BASEDN}
+dMDLocation: CN=Schema,CN=Configuration,${BASEDN}
+objectGUID: ${INVOCATIONID}
+invocationId: ${INVOCATIONID}
+msDS-Behavior-Version: 2
+
+dn: CN=Services,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: container
+cn: Services
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+systemFlags: 0x80000000
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=Windows NT,CN=Services,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: container
+cn: Windows NT
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
+
+dn: CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: nTDSService
+cn: Directory Service
+instanceType: 4
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=NTDS-Service,CN=Schema,CN=Configuration,${BASEDN}
+sPNMappings: host=ldap,dns,cifs,http
+
+
+###############################
+# Schema Naming Context
+###############################
+dn: CN=Schema,CN=Configuration,${BASEDN}
+objectClass: top
+objectClass: dMD
+cn: Schema
+instanceType: 13
+uSNCreated: ${USN}
+uSNChanged: ${USN}
+showInAdvancedViewOnly: TRUE
+objectCategory: CN=DMD,CN=Schema,CN=Configuration,${BASEDN}
+masteredBy: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+msDs-masteredBy: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+fSMORoleOwner: CN=NTDS Settings,CN=${NETBIOSNAME},CN=Servers,CN=${DEFAULTSITE},CN=Sites,CN=Configuration,${BASEDN}
+objectVersion: 30
--- /dev/null
+dn: @INDEXLIST
+@IDXATTR: cn
+@IDXATTR: flatname
+@IDXATTR: realm
+
+dn: @ATTRIBUTES
+realm: CASE_INSENSITIVE
+flatname: CASE_INSENSITIVE
+sAMAccountName: CASE_INSENSITIVE
+
+#Add modules to the list to activate them by default
+#beware often order is important
+dn: @MODULES
+@LIST: timestamps
+
+dn: CN=LSA Secrets
+objectClass: top
+objectClass: container
+cn: LSA Secrets
+
+dn: CN=Primary Domains
+objectClass: top
+objectClass: container
+cn: Primary Domains
+
+dn: flatname=${DOMAIN},CN=Primary Domains
+objectClass: top
+objectClass: primaryDomain
+flatname: ${DOMAIN}
+realm: ${REALM}
+secret: ${MACHINEPASS}
+secureChannelType: 6
+sAMAccountName: ${NETBIOSNAME}$
+whenCreated: ${LDAPTIME}
+whenChanged: ${LDAPTIME}
+msDS-KeyVersionNumber: 1
+objectSid: ${DOMAINSID}
if (error_string) {
*error_string = strdup(nt_errstr(status));
}
+ return status;
}
validation_level = r->in.validation_level;
+
+ creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r->out.validation);
+
switch (validation_level) {
case 2:
base = &r->out.validation.sam2->base;
if (error_string) {
*error_string = strdup(nt_errstr(status));
}
+ return status;
}
validation_level = r_ex->in.validation_level;
+
+ creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_ex->out.validation);
+
switch (validation_level) {
case 2:
base = &r_ex->out.validation.sam2->base;
if (error_string) {
*error_string = strdup(nt_errstr(status));
}
+ return status;
}
-
+
validation_level = r_flags->in.validation_level;
+
+ creds_decrypt_samlogon(samlogon_state->creds, validation_level, &r_flags->out.validation);
+
switch (validation_level) {
case 2:
base = &r_flags->out.validation.sam2->base;
break;
}
-
- if (!NT_STATUS_IS_OK(status)) {
- /* we cannot check the session key, if the logon failed... */
- return status;
- }
-
if (!base) {
printf("No user info returned from 'successful' SamLogon*() call!\n");
return NT_STATUS_INVALID_PARAMETER;
}
- /* find and decyrpt the session keys, return in parameters above */
- if (validation_level == 6) {
- /* they aren't encrypted! */
- if (user_session_key) {
- memcpy(user_session_key, base->key.key, 16);
- }
- if (lm_key) {
- memcpy(lm_key, base->LMSessKey.key, 8);
- }
- } else if (samlogon_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
- static const char zeros[16];
-
- if (memcmp(base->key.key, zeros,
- sizeof(base->key.key)) != 0) {
- creds_arcfour_crypt(samlogon_state->creds,
- base->key.key,
- sizeof(base->key.key));
- }
-
- if (user_session_key) {
- memcpy(user_session_key, base->key.key, 16);
- }
-
- if (memcmp(base->LMSessKey.key, zeros,
- sizeof(base->LMSessKey.key)) != 0) {
- creds_arcfour_crypt(samlogon_state->creds,
- base->LMSessKey.key,
- sizeof(base->LMSessKey.key));
- }
-
- if (lm_key) {
- memcpy(lm_key, base->LMSessKey.key, 8);
- }
- } else {
- static const char zeros[16];
-
- if (user_session_key) {
- memcpy(user_session_key, base->key.key, 16);
- }
-
- if (memcmp(base->LMSessKey.key, zeros,
- sizeof(base->LMSessKey.key)) != 0) {
- creds_des_decrypt_LMKey(samlogon_state->creds,
- &base->LMSessKey);
- }
-
- if (lm_key) {
- memcpy(lm_key, base->LMSessKey.key, 8);
- }
+ if (user_session_key) {
+ memcpy(user_session_key, base->key.key, 16);
}
-
+ if (lm_key) {
+ memcpy(lm_key, base->LMSessKey.key, 8);
+ }
+
return status;
}
winbind/wb_server.o \
winbind/wb_samba3_protocol.o \
winbind/wb_samba3_cmd.o \
+ winbind/wb_init_domain.o \
winbind/wb_async_helpers.o
REQUIRED_SUBSYSTEMS = RPC_NDR_LSA
# End MODULE server_service_winbind
#include "librpc/gen_ndr/ndr_lsa.h"
#include "libcli/auth/credentials.h"
-static BOOL comp_is_ok(struct composite_context *ctx)
-{
- if (NT_STATUS_IS_OK(ctx->status)) {
- return True;
- }
- ctx->state = COMPOSITE_STATE_ERROR;
- if (ctx->async.fn != NULL) {
- ctx->async.fn(ctx);
- }
- return False;
-}
+struct finddcs_state {
+ struct composite_context *ctx;
+ struct messaging_context *msg_ctx;
-static void comp_error(struct composite_context *ctx, NTSTATUS status)
-{
- ctx->status = status;
- SMB_ASSERT(!comp_is_ok(ctx));
-}
+ const char *domain_name;
+ const struct dom_sid *domain_sid;
-static BOOL comp_nomem(const void *p, struct composite_context *ctx)
-{
- if (p != NULL) {
- return False;
- }
- comp_error(ctx, NT_STATUS_NO_MEMORY);
- return True;
-}
+ struct nbtd_getdcname r;
-static void comp_done(struct composite_context *ctx)
-{
- ctx->state = COMPOSITE_STATE_DONE;
- if (ctx->async.fn != NULL) {
- ctx->async.fn(ctx);
- }
-}
+ int num_dcs;
+ struct nbt_dc_name *dcs;
+};
-static void comp_cont(struct composite_context *ctx,
- struct composite_context *new_ctx,
- void (*continuation)(struct composite_context *),
- void *private_data)
-{
- if (comp_nomem(new_ctx, ctx)) return;
- new_ctx->async.fn = continuation;
- new_ctx->async.private_data = private_data;
-}
+static void finddcs_resolve(struct composite_context *ctx);
+static void finddcs_getdc(struct irpc_request *ireq);
-static void rpc_cont(struct composite_context *ctx,
- struct rpc_request *new_req,
- void (*continuation)(struct rpc_request *),
- void *private_data)
+struct composite_context *wb_finddcs_send(const char *domain_name,
+ const struct dom_sid *domain_sid,
+ struct event_context *event_ctx,
+ struct messaging_context *msg_ctx)
{
- if (comp_nomem(new_req, ctx)) return;
- new_req->async.callback = continuation;
- new_req->async.private = private_data;
-}
+ struct composite_context *result, *ctx;
+ struct finddcs_state *state;
+ struct nbt_name name;
-struct finddcs_state {
- struct wb_finddcs *io;
- struct composite_context *creq;
+ result = talloc_zero(NULL, struct composite_context);
+ if (result == NULL) goto failed;
+ result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->event_ctx = event_ctx;
- struct nbtd_getdcname *r;
- struct irpc_request *ireq;
-};
+ state = talloc(result, struct finddcs_state);
+ if (state == NULL) goto failed;
+ state->ctx = result;
+ result->private_data = state;
-static void finddcs_getdc(struct irpc_request *ireq)
-{
- struct composite_context *c = talloc_get_type(ireq->async.private,
- struct composite_context);
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
+ state->domain_name = talloc_strdup(state, domain_name);
+ if (state->domain_name == NULL) goto failed;
+ state->domain_sid = dom_sid_dup(state, domain_sid);
+ if (state->domain_sid == NULL) goto failed;
+ state->msg_ctx = msg_ctx;
- c->status = irpc_call_recv(ireq);
- if (!comp_is_ok(c)) return;
+ make_nbt_name(&name, state->domain_name, 0x1c);
+ ctx = resolve_name_send(&name, result->event_ctx,
+ lp_name_resolve_order());
- state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs,
- state->r->out.dcname);
- comp_done(c);
+ if (ctx == NULL) goto failed;
+ ctx->async.fn = finddcs_resolve;
+ ctx->async.private_data = state;
+
+ return result;
+
+failed:
+ talloc_free(result);
+ return NULL;
}
-/*
- called when name resolution is finished
-*/
-static void finddcs_resolve(struct composite_context *res_ctx)
+static void finddcs_resolve(struct composite_context *ctx)
{
- struct composite_context *c = talloc_get_type(res_ctx->async.private_data,
- struct composite_context);
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
+ struct finddcs_state *state =
+ talloc_get_type(ctx->async.private_data, struct finddcs_state);
+ struct irpc_request *ireq;
uint32_t *nbt_servers;
+ const char *address;
- state->io->out.num_dcs = 1;
- state->io->out.dcs = talloc_array(state, struct nbt_dc_name,
- state->io->out.num_dcs);
- if (comp_nomem(state->io->out.dcs, c)) return;
+ state->ctx->status = resolve_name_recv(ctx, state, &address);
+ if (!comp_is_ok(state->ctx)) return;
- c->status = resolve_name_recv(res_ctx, state->io->out.dcs,
- &state->io->out.dcs[0].address);
- if (!comp_is_ok(c)) return;
+ state->num_dcs = 1;
+ state->dcs = talloc_array(state, struct nbt_dc_name, state->num_dcs);
+ if (comp_nomem(state->dcs, state->ctx)) return;
- nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server");
- if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
- comp_error(c, NT_STATUS_NO_LOGON_SERVERS);
- return;
- }
+ state->dcs[0].address = talloc_steal(state->dcs, address);
- state->r = talloc(state, struct nbtd_getdcname);
- if (comp_nomem(state->r, c)) return;
-
- state->r->in.domainname = talloc_strdup(state->r, lp_workgroup());
- if (comp_nomem(state->r->in.domainname, c)) return;
- state->r->in.ip_address = state->io->out.dcs[0].address;
- state->r->in.my_computername = lp_netbios_name();
- state->r->in.my_accountname =
- talloc_asprintf(state->r, "%s$", lp_netbios_name());
- if (comp_nomem(state->r->in.my_accountname, c)) return;
- state->r->in.account_control = ACB_WSTRUST;
- state->r->in.domain_sid =
- secrets_get_domain_sid(state->r, lp_workgroup());
-
- if (state->r->in.domain_sid == NULL) {
- comp_error(c, NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
+ nbt_servers = irpc_servers_byname(state->msg_ctx, "nbt_server");
+ if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
+ comp_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
return;
}
- state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0],
- &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
- state->r, state);
- if (comp_nomem(state->ireq, c)) return;
+ state->r.in.domainname = state->domain_name;
+ state->r.in.ip_address = state->dcs[0].address;
+ state->r.in.my_computername = lp_netbios_name();
+ state->r.in.my_accountname = talloc_asprintf(state, "%s$",
+ lp_netbios_name());
+ if (comp_nomem(state->r.in.my_accountname, state->ctx)) return;
+ state->r.in.account_control = ACB_WSTRUST;
+ state->r.in.domain_sid = dom_sid_dup(state, state->domain_sid);
+ if (comp_nomem(state->r.in.domain_sid, state->ctx)) return;
- c->status = NT_STATUS_OK;
- state->ireq->async.fn = finddcs_getdc;
- state->ireq->async.private = c;
+ ireq = irpc_call_send(state->msg_ctx, nbt_servers[0],
+ &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
+ &state->r, state);
+ irpc_cont(state->ctx, ireq, finddcs_getdc, state);
}
-struct composite_context *wb_finddcs_send(struct wb_finddcs *io,
- struct event_context *event_ctx)
+static void finddcs_getdc(struct irpc_request *ireq)
{
- struct composite_context *c;
- struct finddcs_state *state;
- struct nbt_name name;
-
- c = talloc_zero(NULL, struct composite_context);
- if (c == NULL) goto failed;
- c->state = COMPOSITE_STATE_IN_PROGRESS;
- c->event_ctx = event_ctx;
-
- state = talloc(c, struct finddcs_state);
- if (state == NULL) goto failed;
- state->io = io;
+ struct finddcs_state *state =
+ talloc_get_type(ireq->async.private, struct finddcs_state);
- make_nbt_name(&name, io->in.domain, 0x1c);
- state->creq = resolve_name_send(&name, c->event_ctx,
- lp_name_resolve_order());
-
- if (state->creq == NULL) goto failed;
- state->creq->async.private_data = c;
- state->creq->async.fn = finddcs_resolve;
- c->private_data = state;
+ state->ctx->status = irpc_call_recv(ireq);
+ if (!comp_is_ok(state->ctx)) return;
- return c;
-failed:
- talloc_free(c);
- return NULL;
+ state->dcs[0].name = talloc_steal(state->dcs, state->r.out.dcname);
+ comp_done(state->ctx);
}
-NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
+NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
+ int *num_dcs, struct nbt_dc_name **dcs)
{
- NTSTATUS status;
-
- status = composite_wait(c);
-
+ NTSTATUS status =composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
- talloc_steal(mem_ctx, state->io->out.dcs);
+ struct finddcs_state *state =
+ talloc_get_type(c->private_data, struct finddcs_state);
+ *num_dcs = state->num_dcs;
+ *dcs = talloc_steal(mem_ctx, state->dcs);
}
-
talloc_free(c);
return status;
}
-NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx,
- struct event_context *ev)
+NTSTATUS wb_finddcs(const char *domain_name, const struct dom_sid *domain_sid,
+ struct event_context *event_ctx,
+ struct messaging_context *msg_ctx,
+ TALLOC_CTX *mem_ctx,
+ int *num_dcs, struct nbt_dc_name **dcs)
{
- struct composite_context *c = wb_finddcs_send(io, ev);
- return wb_finddcs_recv(c, mem_ctx);
+ struct composite_context *c = wb_finddcs_send(domain_name, domain_sid,
+ event_ctx, msg_ctx);
+ return wb_finddcs_recv(c, mem_ctx, num_dcs, dcs);
}
struct get_schannel_creds_state {
DCERPC_NETLOGON_VERSION);
if (!comp_is_ok(state->ctx)) return;
- ZERO_STRUCT(state->r);
state->r.in.computer_name =
cli_credentials_get_workstation(state->wks_creds);
state->r.in.server_name =
state->r.out.credentials, mach_pwd,
&state->netr_cred, state->negotiate_flags);
- ZERO_STRUCT(state->a);
state->a.in.server_name =
talloc_reference(state, state->r.in.server_name);
state->a.in.account_name =
return wb_get_schannel_creds_recv(c, mem_ctx, netlogon_pipe);
}
-struct get_lsa_pipe_state {
- struct composite_context *ctx;
- const char *domain;
-
- struct wb_finddcs *finddcs;
- struct smb_composite_connect *conn;
- struct dcerpc_pipe *lsa_pipe;
-
- struct lsa_ObjectAttribute objectattr;
- struct lsa_OpenPolicy2 openpolicy;
- struct policy_handle policy_handle;
-
- struct lsa_QueryInfoPolicy queryinfo;
-
- struct lsa_Close close;
-};
-
-static void get_lsa_pipe_recv_dcs(struct composite_context *ctx);
-static void get_lsa_pipe_recv_tree(struct composite_context *ctx);
-static void get_lsa_pipe_recv_pipe(struct composite_context *ctx);
-static void get_lsa_pipe_recv_openpol(struct rpc_request *req);
-static void get_lsa_pipe_recv_queryinfo(struct rpc_request *req);
-static void get_lsa_pipe_recv_close(struct rpc_request *req);
-
-struct composite_context *wb_get_lsa_pipe_send(struct event_context *event_ctx,
- struct messaging_context *msg_ctx,
- const char *domain)
-{
- struct composite_context *result, *ctx;
- struct get_lsa_pipe_state *state;
-
- result = talloc_zero(NULL, struct composite_context);
- if (result == NULL) goto failed;
- result->state = COMPOSITE_STATE_IN_PROGRESS;
- result->event_ctx = event_ctx;
-
- state = talloc(result, struct get_lsa_pipe_state);
- if (state == NULL) goto failed;
- result->private_data = state;
- state->ctx = result;
-
- state->domain = domain;
-
- state->finddcs = talloc(state, struct wb_finddcs);
- if (state->finddcs == NULL) goto failed;
-
- state->finddcs->in.msg_ctx = msg_ctx;
- state->finddcs->in.domain = lp_workgroup();
-
- ctx = wb_finddcs_send(state->finddcs, event_ctx);
- if (ctx == NULL) goto failed;
-
- ctx->async.fn = get_lsa_pipe_recv_dcs;
- ctx->async.private_data = state;
- return result;
-
- failed:
- talloc_free(result);
- return NULL;
-}
-
-static void get_lsa_pipe_recv_dcs(struct composite_context *ctx)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(ctx->async.private_data,
- struct get_lsa_pipe_state);
-
- state->ctx->status = wb_finddcs_recv(ctx, state);
- if (!comp_is_ok(state->ctx)) return;
-
- state->conn = talloc(state, struct smb_composite_connect);
- if (comp_nomem(state->conn, state->ctx)) return;
-
- state->conn->in.dest_host = state->finddcs->out.dcs[0].address;
- state->conn->in.port = 0;
- state->conn->in.called_name = state->finddcs->out.dcs[0].name;
- state->conn->in.service = "IPC$";
- state->conn->in.service_type = "IPC";
- state->conn->in.workgroup = lp_workgroup();
-
- state->conn->in.credentials = cli_credentials_init(state->conn);
- if (comp_nomem(state->conn->in.credentials, state->ctx)) return;
- cli_credentials_set_conf(state->conn->in.credentials);
- cli_credentials_set_anonymous(state->conn->in.credentials);
-
- ctx = smb_composite_connect_send(state->conn, state,
- state->ctx->event_ctx);
- comp_cont(state->ctx, ctx, get_lsa_pipe_recv_tree, state);
-}
-
-static void get_lsa_pipe_recv_tree(struct composite_context *ctx)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(ctx->async.private_data,
- struct get_lsa_pipe_state);
-
- state->ctx->status = smb_composite_connect_recv(ctx, state);
- if (!comp_is_ok(state->ctx)) return;
-
- state->lsa_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
- if (comp_nomem(state->lsa_pipe, state->ctx)) return;
-
- ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe->conn,
- state->conn->out.tree, "\\lsarpc");
- comp_cont(state->ctx, ctx, get_lsa_pipe_recv_pipe, state);
-}
-
-static void get_lsa_pipe_recv_pipe(struct composite_context *ctx)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(ctx->async.private_data,
- struct get_lsa_pipe_state);
- struct rpc_request *req;
-
- state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
- if (!comp_is_ok(state->ctx)) return;
-
- talloc_unlink(state, state->conn->out.tree); /* The pipe owns it now */
- state->conn->out.tree = NULL;
-
- state->ctx->status = dcerpc_bind_auth_none(state->lsa_pipe,
- DCERPC_LSARPC_UUID,
- DCERPC_LSARPC_VERSION);
- if (!comp_is_ok(state->ctx)) return;
-
- ZERO_STRUCT(state->openpolicy);
- state->openpolicy.in.system_name =
- talloc_asprintf(state, "\\\\%s",
- dcerpc_server_name(state->lsa_pipe));
- if (comp_nomem(state->openpolicy.in.system_name, state->ctx)) return;
-
- ZERO_STRUCT(state->objectattr);
- state->openpolicy.in.attr = &state->objectattr;
- state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- state->openpolicy.out.handle = &state->policy_handle;
-
- req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
- &state->openpolicy);
- rpc_cont(state->ctx, req, get_lsa_pipe_recv_openpol, state);
-}
-
-static void get_lsa_pipe_recv_openpol(struct rpc_request *req)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(req->async.private, struct get_lsa_pipe_state);
-
- state->ctx->status = dcerpc_ndr_request_recv(req);
- if (!comp_is_ok(state->ctx)) return;
- state->ctx->status = state->openpolicy.out.result;
- if (!comp_is_ok(state->ctx)) return;
-
- ZERO_STRUCT(state->queryinfo);
- state->queryinfo.in.handle = &state->policy_handle;
- state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
-
- req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state,
- &state->queryinfo);
- rpc_cont(state->ctx, req, get_lsa_pipe_recv_queryinfo, state);
-}
-
-static void get_lsa_pipe_recv_queryinfo(struct rpc_request *req)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(req->async.private, struct get_lsa_pipe_state);
-
- state->ctx->status = dcerpc_ndr_request_recv(req);
- if (!comp_is_ok(state->ctx)) return;
- state->ctx->status = state->queryinfo.out.result;
- if (!comp_is_ok(state->ctx)) return;
-
- ZERO_STRUCT(state->close);
- state->close.in.handle = &state->policy_handle;
- state->close.out.handle = &state->policy_handle;
-
- req = dcerpc_lsa_Close_send(state->lsa_pipe, state,
- &state->close);
- rpc_cont(state->ctx, req, get_lsa_pipe_recv_close, state);
-}
-
-static void get_lsa_pipe_recv_close(struct rpc_request *req)
-{
- struct get_lsa_pipe_state *state =
- talloc_get_type(req->async.private, struct get_lsa_pipe_state);
-
- state->ctx->status = dcerpc_ndr_request_recv(req);
- if (!comp_is_ok(state->ctx)) return;
- state->ctx->status = state->close.out.result;
- if (!comp_is_ok(state->ctx)) return;
-
- comp_done(state->ctx);
-}
-
-NTSTATUS wb_get_lsa_pipe_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
- struct dom_sid **sid, struct dcerpc_pipe **pipe)
-{
- NTSTATUS status = composite_wait(c);
- if (NT_STATUS_IS_OK(status)) {
- struct get_lsa_pipe_state *state =
- talloc_get_type(c->private_data,
- struct get_lsa_pipe_state);
- *sid = talloc_steal(mem_ctx,
- state->queryinfo.out.info->domain.sid);
- *pipe = talloc_steal(mem_ctx, state->lsa_pipe);
- }
- talloc_free(c);
- return status;
-}
-
-NTSTATUS wb_get_lsa_pipe(struct event_context *event_ctx,
- struct messaging_context *msg_ctx,
- const char *domain,
- TALLOC_CTX *mem_ctx,
- struct dom_sid **sid,
- struct dcerpc_pipe **pipe)
-{
- struct composite_context *c =
- wb_get_lsa_pipe_send(event_ctx, msg_ctx, domain);
- return wb_get_lsa_pipe_recv(c, mem_ctx, sid, pipe);
-}
-
struct lsa_lookupnames_state {
struct composite_context *ctx;
uint32_t num_names;
return wb_lsa_lookupnames_recv(c, mem_ctx, sids);
}
-struct lsa_lookupname_state {
- struct composite_context *ctx;
- struct dcerpc_pipe *lsa_pipe;
- const char *name;
- struct wb_sid_object *sid;
-
- struct lsa_ObjectAttribute objectattr;
- struct lsa_OpenPolicy2 openpolicy;
- struct policy_handle policy_handle;
- struct lsa_Close close;
-};
-
-static void lsa_lookupname_recv_open(struct rpc_request *req);
-static void lsa_lookupname_recv_sids(struct composite_context *ctx);
-
-struct composite_context *wb_lsa_lookupname_send(struct dcerpc_pipe *lsa_pipe,
- const char *name)
-{
- struct composite_context *result;
- struct rpc_request *req;
- struct lsa_lookupname_state *state;
-
- result = talloc_zero(NULL, struct composite_context);
- if (result == NULL) goto failed;
- result->state = COMPOSITE_STATE_IN_PROGRESS;
- result->event_ctx = lsa_pipe->conn->event_ctx;
-
- state = talloc(result, struct lsa_lookupname_state);
- if (state == NULL) goto failed;
- result->private_data = state;
-
- state->lsa_pipe = lsa_pipe;
- state->name = talloc_strdup(state, name);
- if (state->name == NULL) goto failed;
- state->ctx = result;
-
- ZERO_STRUCT(state->openpolicy);
- state->openpolicy.in.system_name =
- talloc_asprintf(state, "\\\\%s",
- dcerpc_server_name(state->lsa_pipe));
- ZERO_STRUCT(state->objectattr);
- state->openpolicy.in.attr = &state->objectattr;
- state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- state->openpolicy.out.handle = &state->policy_handle;
-
- req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
- &state->openpolicy);
- if (req == NULL) goto failed;
-
- req->async.callback = lsa_lookupname_recv_open;
- req->async.private = state;
- return result;
-
- failed:
- talloc_free(result);
- return NULL;
-}
-
-static void lsa_lookupname_recv_open(struct rpc_request *req)
-{
- struct lsa_lookupname_state *state =
- talloc_get_type(req->async.private,
- struct lsa_lookupname_state);
- struct composite_context *ctx;
-
- state->ctx->status = dcerpc_ndr_request_recv(req);
- if (!comp_is_ok(state->ctx)) return;
- state->ctx->status = state->openpolicy.out.result;
- if (!comp_is_ok(state->ctx)) return;
-
- ctx = wb_lsa_lookupnames_send(state->lsa_pipe, &state->policy_handle,
- 1, &state->name);
- comp_cont(state->ctx, ctx, lsa_lookupname_recv_sids, state);
-}
-
-static void lsa_lookupname_recv_sids(struct composite_context *ctx)
-{
- struct lsa_lookupname_state *state =
- talloc_get_type(ctx->async.private_data,
- struct lsa_lookupname_state);
- struct rpc_request *req;
- struct wb_sid_object **sids;
-
- state->ctx->status = wb_lsa_lookupnames_recv(ctx, state, &sids);
-
- if (NT_STATUS_IS_OK(state->ctx->status)) {
- state->sid = NULL;
- if (sids != NULL) {
- state->sid = sids[0];
- }
- }
-
- ZERO_STRUCT(state->close);
- state->close.in.handle = &state->policy_handle;
- state->close.out.handle = &state->policy_handle;
-
- req = dcerpc_lsa_Close_send(state->lsa_pipe, state,
- &state->close);
- if (req != NULL) {
- req->async.callback =
- (void(*)(struct rpc_request *))talloc_free;
- }
-
- comp_done(state->ctx);
-}
-
-NTSTATUS wb_lsa_lookupname_recv(struct composite_context *c,
- TALLOC_CTX *mem_ctx,
- struct wb_sid_object **sid)
-{
- NTSTATUS status = composite_wait(c);
- if (NT_STATUS_IS_OK(status)) {
- struct lsa_lookupname_state *state =
- talloc_get_type(c->private_data,
- struct lsa_lookupname_state);
- *sid = talloc_steal(mem_ctx, state->sid);
- }
- talloc_free(c);
- return status;
-}
-
-NTSTATUS wb_lsa_lookupname(struct dcerpc_pipe *lsa_pipe, const char *name,
- TALLOC_CTX *mem_ctx, struct wb_sid_object **sid)
-{
- struct composite_context *c =
- wb_lsa_lookupname_send(lsa_pipe, name);
- return wb_lsa_lookupname_recv(c, mem_ctx, sid);
-}
-
struct cmd_lookupname_state {
struct composite_context *ctx;
struct wbsrv_call *call;
+ struct wbsrv_domain *domain;
const char *name;
struct wb_sid_object *result;
};
-static void cmd_lookupname_recv_lsa(struct composite_context *ctx);
+static void cmd_lookupname_recv_init(struct composite_context *ctx);
static void cmd_lookupname_recv_sid(struct composite_context *ctx);
struct composite_context *wb_cmd_lookupname_send(struct wbsrv_call *call,
state->call = call;
state->name = talloc_strdup(state, name);
- if (service->lsa_pipe != NULL) {
- ctx = wb_lsa_lookupname_send(service->lsa_pipe, name);
+ state->domain = service->domains;
+
+ if (state->domain->initialized) {
+ ctx = wb_lsa_lookupnames_send(state->domain->lsa_pipe,
+ state->domain->lsa_policy,
+ 1, &name);
if (ctx == NULL) goto failed;
ctx->async.fn = cmd_lookupname_recv_sid;
ctx->async.private_data = state;
return result;
}
- ctx = wb_get_lsa_pipe_send(result->event_ctx,
- call->wbconn->conn->msg_ctx,
- lp_workgroup());
+ ctx = wb_init_domain_send(state->domain,
+ result->event_ctx,
+ call->wbconn->conn->msg_ctx);
if (ctx == NULL) goto failed;
- ctx->async.fn = cmd_lookupname_recv_lsa;
+ ctx->async.fn = cmd_lookupname_recv_init;
ctx->async.private_data = state;
return result;
return NULL;
}
-static void cmd_lookupname_recv_lsa(struct composite_context *ctx)
+static void cmd_lookupname_recv_init(struct composite_context *ctx)
{
struct cmd_lookupname_state *state =
talloc_get_type(ctx->async.private_data,
struct cmd_lookupname_state);
- struct wbsrv_service *service =
- state->call->wbconn->listen_socket->service;
- struct dom_sid *sid;
- struct dcerpc_pipe *pipe;
-
- state->ctx->status = wb_get_lsa_pipe_recv(ctx, state, &sid, &pipe);
+ state->ctx->status = wb_init_domain_recv(ctx);
if (!comp_is_ok(state->ctx)) return;
- if (service->lsa_pipe == NULL) {
- /* Only put the new pipe in if nobody else was faster. */
- service->lsa_pipe = talloc_steal(service, pipe);
- }
-
- ctx = wb_lsa_lookupname_send(service->lsa_pipe, state->name);
+ ctx = wb_lsa_lookupnames_send(state->domain->lsa_pipe,
+ state->domain->lsa_policy,
+ 1, &state->name);
comp_cont(state->ctx, ctx, cmd_lookupname_recv_sid, state);
}
struct cmd_lookupname_state *state =
talloc_get_type(ctx->async.private_data,
struct cmd_lookupname_state);
+ struct wb_sid_object **sids;
+
+ state->ctx->status = wb_lsa_lookupnames_recv(ctx, state, &sids);
+ state->result = sids[0];
- state->ctx->status = wb_lsa_lookupname_recv(ctx, state,
- &state->result);
if (!comp_is_ok(state->ctx)) return;
comp_done(state->ctx);
struct cmd_checkmachacc_state {
struct composite_context *ctx;
struct wbsrv_call *call;
- struct cli_credentials *wks_creds;
+ struct wbsrv_domain *domain;
};
-static void cmd_checkmachacc_recv_lsa(struct composite_context *ctx);
-static void cmd_checkmachacc_recv_creds(struct composite_context *ctx);
+static void cmd_checkmachacc_recv_init(struct composite_context *ctx);
struct composite_context *wb_cmd_checkmachacc_send(struct wbsrv_call *call)
{
result->private_data = state;
state->call = call;
- state->wks_creds = cli_credentials_init(state);
- if (state->wks_creds == NULL) goto failed;
-
- cli_credentials_set_conf(state->wks_creds);
-
- state->ctx->status =
- cli_credentials_set_machine_account(state->wks_creds);
- if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;
-
- if (service->netlogon_pipe != NULL) {
- talloc_free(service->netlogon_pipe);
- service->netlogon_pipe = NULL;
- }
-
- if (service->lsa_pipe != NULL) {
- struct smbcli_tree *tree =
- dcerpc_smb_tree(service->lsa_pipe->conn);
-
- if (tree == NULL) goto failed;
-
- ctx = wb_get_schannel_creds_send(state->wks_creds, tree,
- result->event_ctx);
- if (ctx == NULL) goto failed;
-
- ctx->async.fn = cmd_checkmachacc_recv_creds;
- ctx->async.private_data = state;
- return result;
- }
+ state->domain = service->domains;
- ctx = wb_get_lsa_pipe_send(result->event_ctx,
- call->wbconn->conn->msg_ctx,
- lp_workgroup());
+ ctx = wb_init_domain_send(state->domain, result->event_ctx,
+ call->wbconn->conn->msg_ctx);
if (ctx == NULL) goto failed;
- ctx->async.fn = cmd_checkmachacc_recv_lsa;
+ ctx->async.fn = cmd_checkmachacc_recv_init;
ctx->async.private_data = state;
return result;
return NULL;
}
-static void cmd_checkmachacc_recv_lsa(struct composite_context *ctx)
-{
- struct cmd_checkmachacc_state *state =
- talloc_get_type(ctx->async.private_data,
- struct cmd_checkmachacc_state);
- struct wbsrv_service *service =
- state->call->wbconn->listen_socket->service;
-
- struct dom_sid *sid;
- struct dcerpc_pipe *pipe;
- struct smbcli_tree *tree;
-
- state->ctx->status = wb_get_lsa_pipe_recv(ctx, state, &sid, &pipe);
- if (!comp_is_ok(state->ctx)) return;
-
- if (service->lsa_pipe == NULL) {
- service->lsa_pipe = talloc_steal(service, pipe);
- }
-
- tree = dcerpc_smb_tree(service->lsa_pipe->conn);
-
- if (tree == NULL) {
- comp_error(state->ctx, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- ctx = wb_get_schannel_creds_send(state->wks_creds, tree,
- state->ctx->event_ctx);
- comp_cont(state->ctx, ctx, cmd_checkmachacc_recv_creds, state);
-}
-
-static void cmd_checkmachacc_recv_creds(struct composite_context *ctx)
+static void cmd_checkmachacc_recv_init(struct composite_context *ctx)
{
struct cmd_checkmachacc_state *state =
talloc_get_type(ctx->async.private_data,
struct cmd_checkmachacc_state);
- struct wbsrv_service *service =
- state->call->wbconn->listen_socket->service;
- struct dcerpc_pipe *pipe;
- state->ctx->status = wb_get_schannel_creds_recv(ctx, state, &pipe);
+ state->ctx->status = wb_init_domain_recv(ctx);
if (!comp_is_ok(state->ctx)) return;
- if (service->netlogon_pipe != NULL) {
- /* Someone else was faster, we need to replace it with our
- * pipe */
- talloc_free(service->netlogon_pipe);
- }
-
- service->netlogon_pipe = talloc_steal(service, pipe);
-
comp_done(state->ctx);
}
NTSTATUS wb_cmd_checkmachacc_recv(struct composite_context *c)
{
- return composite_wait(c);
+ NTSTATUS status = composite_wait(c);
+ talloc_free(c);
+ return status;
}
NTSTATUS wb_cmd_checkmachacc(struct wbsrv_call *call)
#include "librpc/gen_ndr/lsa.h"
-struct wb_finddcs {
- struct {
- struct messaging_context *msg_ctx;
- const char *domain;
- } in;
-
- struct {
- int num_dcs;
- struct nbt_dc_name {
- const char *address;
- const char *name;
- } *dcs;
- } out;
+struct nbt_dc_name {
+ const char *address;
+ const char *name;
};
struct wb_sid_object {
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Volker Lendecke 2005
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+ a composite API for initializing a domain
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "libcli/smb_composite/smb_composite.h"
+#include "winbind/wb_async_helpers.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_stream.h"
+
+#include "librpc/gen_ndr/nbt.h"
+#include "librpc/gen_ndr/samr.h"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/irpc.h"
+#include "librpc/gen_ndr/ndr_irpc.h"
+#include "libcli/raw/libcliraw.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_lsa.h"
+#include "libcli/auth/credentials.h"
+
+
+/* Helper to initialize LSA with different auth methods and opening the lsa
+ * policy */
+
+struct init_lsa_state {
+ struct composite_context *ctx;
+ struct dcerpc_pipe *lsa_pipe;
+
+ uint8_t auth_type;
+ struct cli_credentials *creds;
+
+ struct lsa_ObjectAttribute objectattr;
+ struct lsa_OpenPolicy2 openpolicy;
+ struct policy_handle *handle;
+};
+
+static void init_lsa_recv_pipe(struct composite_context *ctx);
+static void init_lsa_recv_openpol(struct rpc_request *req);
+
+static struct composite_context *wb_init_lsa_send(struct smbcli_tree *tree,
+ uint8_t auth_type,
+ struct cli_credentials *creds)
+{
+ struct composite_context *result, *ctx;
+ struct init_lsa_state *state;
+
+ result = talloc(NULL, struct composite_context);
+ if (result == NULL) goto failed;
+ result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->event_ctx = tree->session->transport->socket->event.ctx;
+
+ state = talloc(result, struct init_lsa_state);
+ if (state == NULL) goto failed;
+ state->ctx = result;
+ result->private_data = state;
+
+ state->auth_type = auth_type;
+ state->creds = creds;
+
+ state->lsa_pipe = dcerpc_pipe_init(state, result->event_ctx);
+ if (state->lsa_pipe == NULL) goto failed;
+
+ ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe->conn, tree,
+ "\\lsarpc");
+ ctx->async.fn = init_lsa_recv_pipe;
+ ctx->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void init_lsa_recv_pipe(struct composite_context *ctx)
+{
+ struct init_lsa_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_lsa_state);
+ struct rpc_request *req;
+
+ state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
+ if (!comp_is_ok(state->ctx)) return;
+
+ switch (state->auth_type) {
+ case DCERPC_AUTH_TYPE_NONE:
+ state->ctx->status =
+ dcerpc_bind_auth_none(state->lsa_pipe,
+ DCERPC_LSARPC_UUID,
+ DCERPC_LSARPC_VERSION);
+ break;
+ case DCERPC_AUTH_TYPE_NTLMSSP:
+ case DCERPC_AUTH_TYPE_SCHANNEL:
+ if (state->creds == NULL) {
+ comp_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+ state->lsa_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
+ state->ctx->status =
+ dcerpc_bind_auth_password(state->lsa_pipe,
+ DCERPC_LSARPC_UUID,
+ DCERPC_LSARPC_VERSION,
+ state->creds,
+ state->auth_type,
+ NULL);
+ break;
+ default:
+ state->ctx->status = NT_STATUS_INTERNAL_ERROR;
+
+ }
+
+ state->handle = talloc(state, struct policy_handle);
+ if (comp_nomem(state->handle, state->ctx)) return;
+
+ state->openpolicy.in.system_name =
+ talloc_asprintf(state, "\\\\%s",
+ dcerpc_server_name(state->lsa_pipe));
+ ZERO_STRUCT(state->objectattr);
+ state->openpolicy.in.attr = &state->objectattr;
+ state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ state->openpolicy.out.handle = state->handle;
+
+ req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
+ &state->openpolicy);
+ rpc_cont(state->ctx, req, init_lsa_recv_openpol, state);
+}
+
+static void init_lsa_recv_openpol(struct rpc_request *req)
+{
+ struct init_lsa_state *state =
+ talloc_get_type(req->async.private,
+ struct init_lsa_state);
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!comp_is_ok(state->ctx)) return;
+ state->ctx->status = state->openpolicy.out.result;
+ if (!comp_is_ok(state->ctx)) return;
+
+ comp_done(state->ctx);
+}
+
+static NTSTATUS wb_init_lsa_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe **lsa_pipe,
+ struct policy_handle **lsa_policy)
+{
+ NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_IS_OK(status)) {
+ struct init_lsa_state *state =
+ talloc_get_type(c->private_data,
+ struct init_lsa_state);
+ *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe);
+ *lsa_policy = talloc_steal(mem_ctx, state->handle);
+ }
+ talloc_free(c);
+ return status;
+}
+
+/*
+ * Initialize a domain:
+ *
+ * - With schannel credentials, try to open the SMB connection with the machine
+ * creds. Fall back to anonymous.
+ *
+ * - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
+ * pipe.
+ *
+ * - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
+ * to schannel and then to anon bind.
+ *
+ * - With queryinfopolicy, verify that we're talking to the right domain
+ *
+ * A bit complex, but with all the combinations I think it's the best we can
+ * get. NT4, W2k3 and W2k all have different combinations, but in the end we
+ * have a signed&sealed lsa connection on all of them.
+ *
+ * Not sure if it is overkill, but it seems to work.
+ */
+
+struct init_domain_state {
+ struct composite_context *ctx;
+ struct wbsrv_domain *domain;
+
+ int num_dcs;
+ struct nbt_dc_name *dcs;
+
+ struct smb_composite_connect conn;
+
+ struct dcerpc_pipe *auth2_pipe;
+ struct dcerpc_pipe *netlogon_pipe;
+
+ struct dcerpc_pipe *lsa_pipe;
+ struct policy_handle *lsa_policy;
+
+ struct lsa_QueryInfoPolicy queryinfo;
+};
+
+static void init_domain_recv_dcs(struct composite_context *ctx);
+static void init_domain_recv_authsmb(struct composite_context *ctx);
+static void init_domain_anonsmb(struct init_domain_state *state);
+static void init_domain_recv_anonsmb(struct composite_context *ctx);
+static void init_domain_openpipes(struct init_domain_state *state);
+static void init_domain_openlsa(struct init_domain_state *state);
+static void init_domain_recv_netlogoncreds(struct composite_context *ctx);
+static void init_domain_recv_netlogonpipe(struct composite_context *ctx);
+static void init_domain_recv_lsa_ntlmssp(struct composite_context *ctx);
+static void init_domain_recv_lsa_schannel(struct composite_context *ctx);
+static void init_domain_recv_lsa_none(struct composite_context *ctx);
+static void init_domain_check_lsa(struct init_domain_state *state);
+static void init_domain_recv_queryinfo(struct rpc_request *req);
+
+struct composite_context *wb_init_domain_send(struct wbsrv_domain *domain,
+ struct event_context *event_ctx,
+ struct messaging_context *msg_ctx)
+{
+ struct composite_context *result, *ctx;
+ struct init_domain_state *state;
+
+ result = talloc(domain, struct composite_context);
+ if (result == NULL) goto failed;
+ result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
+ result->event_ctx = event_ctx;
+
+ state = talloc_zero(result, struct init_domain_state);
+ if (state == NULL) goto failed;
+ state->ctx = result;
+ result->private_data = state;
+
+ state->domain = domain;
+
+ if (state->domain->schannel_creds != NULL) {
+ talloc_free(state->domain->schannel_creds);
+ }
+
+ state->domain->schannel_creds = cli_credentials_init(state->domain);
+ if (state->domain->schannel_creds == NULL) goto failed;
+ cli_credentials_set_conf(state->domain->schannel_creds);
+ state->ctx->status =
+ cli_credentials_set_machine_account(state->domain->
+ schannel_creds);
+ if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;
+
+ ctx = wb_finddcs_send(domain->name, domain->sid, event_ctx, msg_ctx);
+ if (ctx == NULL) goto failed;
+
+ ctx->async.fn = init_domain_recv_dcs;
+ ctx->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void init_domain_recv_dcs(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = wb_finddcs_recv(ctx, state, &state->num_dcs,
+ &state->dcs);
+ if (!comp_is_ok(state->ctx)) return;
+
+ if (state->num_dcs < 1) {
+ comp_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
+ return;
+ }
+
+ state->conn.in.dest_host = state->dcs[0].address;
+ state->conn.in.port = 0;
+ state->conn.in.called_name = state->dcs[0].name;
+ state->conn.in.service = "IPC$";
+ state->conn.in.service_type = "IPC";
+ state->conn.in.workgroup = state->domain->name;
+
+ if (state->domain->schannel_creds != NULL) {
+ /* Try to connect as workstation */
+ state->conn.in.credentials = state->domain->schannel_creds;
+ ctx = smb_composite_connect_send(&state->conn, state,
+ state->ctx->event_ctx);
+ comp_cont(state->ctx, ctx, init_domain_recv_authsmb, state);
+ return;
+ }
+
+ init_domain_anonsmb(state);
+}
+
+static void init_domain_recv_authsmb(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = smb_composite_connect_recv(ctx, state);
+ if (NT_STATUS_IS_OK(state->ctx->status)) {
+ init_domain_openpipes(state);
+ return;
+ }
+
+ init_domain_anonsmb(state);
+}
+
+static void init_domain_anonsmb(struct init_domain_state *state)
+{
+ struct composite_context *ctx;
+
+ state->conn.in.credentials = cli_credentials_init(state);
+ if (comp_nomem(state->conn.in.credentials, state->ctx)) return;
+ cli_credentials_set_conf(state->conn.in.credentials);
+ cli_credentials_set_anonymous(state->conn.in.credentials);
+ ctx = smb_composite_connect_send(&state->conn, state,
+ state->ctx->event_ctx);
+ comp_cont(state->ctx, ctx, init_domain_recv_anonsmb, state);
+}
+
+static void init_domain_recv_anonsmb(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = smb_composite_connect_recv(ctx, state);
+ if (!comp_is_ok(state->ctx)) return;
+
+ init_domain_openpipes(state);
+}
+
+static void init_domain_openpipes(struct init_domain_state *state)
+{
+ struct composite_context *ctx;
+
+ if (state->domain->schannel_creds == NULL) {
+ /* No chance to open netlogon */
+ init_domain_openlsa(state);
+ return;
+ }
+
+ ctx = wb_get_schannel_creds_send(state->domain->schannel_creds,
+ state->conn.out.tree,
+ state->ctx->event_ctx);
+ comp_cont(state->ctx, ctx, init_domain_recv_netlogoncreds, state);
+}
+
+static void init_domain_recv_netlogoncreds(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+ struct smbcli_tree *tree = NULL;
+
+ state->ctx->status = wb_get_schannel_creds_recv(ctx, state,
+ &state->auth2_pipe);
+ if (!comp_is_ok(state->ctx)) return;
+
+ talloc_unlink(state, state->conn.out.tree); /* The pipe owns it now */
+
+ state->netlogon_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
+ if (comp_nomem(state->netlogon_pipe, state->ctx)) return;
+
+ if (state->auth2_pipe != NULL) {
+ tree = dcerpc_smb_tree(state->auth2_pipe->conn);
+ }
+
+ if (tree == NULL) {
+ comp_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ ctx = dcerpc_pipe_open_smb_send(state->netlogon_pipe->conn, tree,
+ "\\netlogon");
+ comp_cont(state->ctx, ctx, init_domain_recv_netlogonpipe, state);
+}
+
+static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
+ if (!comp_is_ok(state->ctx)) return;
+
+ state->netlogon_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
+ state->ctx->status =
+ dcerpc_bind_auth_password(state->netlogon_pipe,
+ DCERPC_NETLOGON_UUID,
+ DCERPC_NETLOGON_VERSION,
+ state->domain->schannel_creds,
+ DCERPC_AUTH_TYPE_SCHANNEL,
+ NULL);
+ if (!comp_is_ok(state->ctx)) return;
+
+ init_domain_openlsa(state);
+}
+
+static void init_domain_openlsa(struct init_domain_state *state)
+{
+ struct composite_context *ctx;
+
+ if (state->domain->schannel_creds == NULL) {
+ ctx = wb_init_lsa_send(state->conn.out.tree,
+ DCERPC_AUTH_TYPE_NONE,
+ NULL);
+ comp_cont(state->ctx, ctx, init_domain_recv_lsa_none, state);
+ return;
+ }
+
+ ctx = wb_init_lsa_send(state->conn.out.tree, DCERPC_AUTH_TYPE_NTLMSSP,
+ state->domain->schannel_creds);
+ comp_cont(state->ctx, ctx, init_domain_recv_lsa_ntlmssp, state);
+}
+
+static void init_domain_recv_lsa_ntlmssp(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
+ &state->lsa_policy);
+ if (NT_STATUS_IS_OK(state->ctx->status)) {
+ init_domain_check_lsa(state);
+ return;
+ }
+
+ ctx = wb_init_lsa_send(state->conn.out.tree,
+ DCERPC_AUTH_TYPE_SCHANNEL,
+ state->domain->schannel_creds);
+ comp_cont(state->ctx, ctx, init_domain_recv_lsa_schannel, state);
+}
+
+static void init_domain_recv_lsa_schannel(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
+ &state->lsa_policy);
+ if (NT_STATUS_IS_OK(state->ctx->status)) {
+ init_domain_check_lsa(state);
+ return;
+ }
+
+ ctx = wb_init_lsa_send(state->conn.out.tree,
+ DCERPC_AUTH_TYPE_NONE, NULL);
+ comp_cont(state->ctx, ctx, init_domain_recv_lsa_none, state);
+}
+
+static void init_domain_recv_lsa_none(struct composite_context *ctx)
+{
+ struct init_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct init_domain_state);
+
+ state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
+ &state->lsa_policy);
+ if (!comp_is_ok(state->ctx)) return;
+
+ init_domain_check_lsa(state);
+}
+
+static void init_domain_check_lsa(struct init_domain_state *state)
+{
+ struct rpc_request *req;
+
+ if (state->auth2_pipe == NULL) {
+ /* Give the tree to the LSA pipe, otherwise it has been given
+ * to the auth2 pipe already */
+ talloc_unlink(state, state->conn.out.tree);
+ state->conn.out.tree = NULL;
+ }
+
+ state->queryinfo.in.handle = state->lsa_policy;
+ state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
+
+ req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state,
+ &state->queryinfo);
+ rpc_cont(state->ctx, req, init_domain_recv_queryinfo, state);
+}
+
+static void init_domain_recv_queryinfo(struct rpc_request *req)
+{
+ struct init_domain_state *state =
+ talloc_get_type(req->async.private, struct init_domain_state);
+ struct lsa_DomainInfo *dominfo;
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!comp_is_ok(state->ctx)) return;
+ state->ctx->status = state->queryinfo.out.result;
+ if (!comp_is_ok(state->ctx)) return;
+
+ dominfo = &state->queryinfo.out.info->account_domain;
+
+ if (strcasecmp(state->domain->name, dominfo->name.string) != 0) {
+ DEBUG(2, ("Expected domain name %s, DC %s said %s\n",
+ state->domain->name,
+ dcerpc_server_name(state->lsa_pipe),
+ dominfo->name.string));
+ comp_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
+ return;
+ }
+
+ if (!dom_sid_equal(state->domain->sid, dominfo->sid)) {
+ DEBUG(2, ("Expected domain sid %s, DC %s said %s\n",
+ dom_sid_string(state, state->domain->sid),
+ dcerpc_server_name(state->lsa_pipe),
+ dom_sid_string(state, dominfo->sid)));
+ comp_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
+ return;
+ }
+
+ comp_done(state->ctx);
+}
+
+NTSTATUS wb_init_domain_recv(struct composite_context *c)
+{
+ NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_IS_OK(status)) {
+ struct init_domain_state *state =
+ talloc_get_type(c->private_data,
+ struct init_domain_state);
+ struct wbsrv_domain *domain = state->domain;
+
+ talloc_free(domain->netlogon_auth2_pipe);
+ domain->netlogon_auth2_pipe =
+ talloc_steal(domain, state->auth2_pipe);
+
+ talloc_free(domain->netlogon_pipe);
+ domain->netlogon_pipe =
+ talloc_steal(domain, state->netlogon_pipe);
+
+ talloc_free(domain->lsa_pipe);
+ domain->lsa_pipe =
+ talloc_steal(domain, state->lsa_pipe);
+
+ talloc_free(domain->lsa_policy);
+ domain->lsa_policy =
+ talloc_steal(domain, state->lsa_policy);
+
+ domain->initialized = True;
+ }
+ talloc_free(c);
+ return status;
+}
+
+NTSTATUS wb_init_domain(struct wbsrv_domain *domain,
+ struct event_context *event_ctx,
+ struct messaging_context *messaging_ctx)
+{
+ struct composite_context *c =
+ wb_init_domain_send(domain, event_ctx, messaging_ctx);
+ return wb_init_domain_recv(c);
+}
#include "libcli/smb_composite/smb_composite.h"
#include "include/version.h"
#include "lib/events/events.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
{
return;
}
}
+
+NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
+{
+ struct wbsrv_service *service =
+ s3call->call->wbconn->listen_socket->service;
+
+ s3call->response.result = WINBINDD_ERROR;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
+{
+ struct wbsrv_service *service =
+ s3call->call->wbconn->listen_socket->service;
+ struct creds_CredentialState *creds_state;
+ struct netr_Authenticator auth, auth2;
+ struct netr_NetworkInfo ninfo;
+ struct netr_LogonSamLogon r;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = talloc_new(s3call);
+ if (!mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCT(auth2);
+ creds_state = cli_credentials_get_netlogon_creds(service->domains->schannel_creds);
+
+ creds_client_authenticator(creds_state, &auth);
+
+ ninfo.identity_info.account_name.string = s3call->request.data.auth_crap.user;
+ ninfo.identity_info.domain_name.string = s3call->request.data.auth_crap.domain;
+ ninfo.identity_info.parameter_control = 0;
+ ninfo.identity_info.logon_id_low = 0;
+ ninfo.identity_info.logon_id_high = 0;
+ ninfo.identity_info.workstation.string = s3call->request.data.auth_crap.workstation;
+ memcpy(ninfo.challenge, s3call->request.data.auth_crap.chal,
+ sizeof(ninfo.challenge));
+ ninfo.nt.length = s3call->request.data.auth_crap.nt_resp_len;
+ ninfo.nt.data = s3call->request.data.auth_crap.nt_resp;
+ ninfo.lm.length = s3call->request.data.auth_crap.lm_resp_len;
+ ninfo.lm.data = s3call->request.data.auth_crap.lm_resp;
+
+ r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(service->domains->netlogon_pipe));
+ r.in.workstation = cli_credentials_get_workstation(service->domains->schannel_creds);
+ r.in.credential = &auth;
+ r.in.return_authenticator = &auth2;
+ r.in.logon_level = 2;
+ r.in.validation_level = 3;
+ r.in.logon.network = &ninfo;
+
+ r.out.return_authenticator = NULL;
+ status = dcerpc_netr_LogonSamLogon(service->domains->netlogon_pipe, mem_ctx, &r);
+ if (!r.out.return_authenticator ||
+ !creds_client_check(creds_state, &r.out.return_authenticator->cred)) {
+ DEBUG(0, ("Credentials check failed!\n"));
+ status = NT_STATUS_ACCESS_DENIED;
+ }
+ if (NT_STATUS_IS_OK(status)) {
+ struct netr_SamBaseInfo *base;
+ switch (r.in.validation_level) {
+ case 2:
+ base = &r.out.validation.sam2->base;
+ break;
+ case 3:
+ base = &r.out.validation.sam3->base;
+ break;
+ case 6:
+ base = &r.out.validation.sam6->base;
+ break;
+ }
+
+ creds_decrypt_samlogon(creds_state,
+ r.in.validation_level,
+ &r.out.validation);
+
+ if ((s3call->request.flags & WBFLAG_PAM_INFO3_NDR)
+ && (r.in.validation_level == 3)) {
+ DATA_BLOB tmp_blob, tmp_blob2;
+ status = ndr_push_struct_blob(&tmp_blob, mem_ctx, r.out.validation.sam3,
+ (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
+ if (NT_STATUS_IS_OK(status)) {
+ tmp_blob2 = data_blob_talloc(mem_ctx, NULL, tmp_blob.length + 4);
+ if (!tmp_blob2.data) {
+ status = NT_STATUS_NO_MEMORY;
+ }
+ }
+ /* Ugly Samba3 winbind pipe compatability */
+ if (NT_STATUS_IS_OK(status)) {
+ SIVAL(tmp_blob2.data, 0, 1);
+ memcpy(tmp_blob2.data + 4, tmp_blob.data, tmp_blob.length);
+ }
+ s3call->response.extra_data = talloc_steal(s3call, tmp_blob2.data);
+ s3call->response.length += tmp_blob2.length;
+ }
+ if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
+ memcpy(s3call->response.data.auth.user_session_key,
+ base->key.key, sizeof(s3call->response.data.auth.user_session_key) /* 16 */);
+ }
+ if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
+ memcpy(s3call->response.data.auth.first_8_lm_hash,
+ base->LMSessKey.key, sizeof(s3call->response.data.auth.first_8_lm_hash) /* 8 */);
+ }
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ struct winbindd_response *resp = &s3call->response;
+ resp->result = WINBINDD_ERROR;
+ } else {
+ struct winbindd_response *resp = &s3call->response;
+ resp->result = WINBINDD_OK;
+ }
+
+ WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
+ nt_errstr(status));
+ WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
+ nt_errstr(status));
+ s3call->response.data.auth.pam_error = nt_status_to_pam(status);
+ return NT_STATUS_OK;
+}
case WINBINDD_LOOKUPNAME:
return wbsrv_samba3_lookupname(s3call);
+
+ case WINBINDD_PAM_AUTH:
+ return wbsrv_samba3_pam_auth(s3call);
+
+ case WINBINDD_PAM_AUTH_CRAP:
+ return wbsrv_samba3_pam_auth_crap(s3call);
}
s3call->response.result = WINBINDD_ERROR;
*/
static void wbsrv_accept(struct stream_connection *conn)
{
- struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private,
- struct wbsrv_listen_socket);
+ struct wbsrv_listen_socket *listen_socket =
+ talloc_get_type(conn->private, struct wbsrv_listen_socket);
struct wbsrv_connection *wbconn;
wbconn = talloc_zero(conn, struct wbsrv_connection);
if (!wbconn) {
- stream_terminate_connection(conn, "wbsrv_accept: out of memory");
+ stream_terminate_connection(conn,
+ "wbsrv_accept: out of memory");
return;
}
wbconn->conn = conn;
*/
static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
{
- struct wbsrv_connection *wbconn = talloc_get_type(conn->private, struct wbsrv_connection);
+ struct wbsrv_connection *wbconn =
+ talloc_get_type(conn->private, struct wbsrv_connection);
const struct wbsrv_protocol_ops *ops = wbconn->listen_socket->ops;
struct wbsrv_call *call;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
return;
}
- /* if the used protocol doesn't support pending requests disallow them */
+ /* if the used protocol doesn't support pending requests disallow
+ * them */
if (wbconn->pending_calls && !ops->allow_pending_calls) {
EVENT_FD_NOT_READABLE(conn->event.fde);
return;
uint32_t packet_length;
status = socket_recv(conn->socket,
- wbconn->partial.data + wbconn->partial_read,
+ wbconn->partial.data+wbconn->partial_read,
4 - wbconn->partial_read,
&nread, 0);
if (NT_STATUS_IS_ERR(status)) goto failed;
packet_length = ops->packet_length(wbconn->partial);
- wbconn->partial.data = talloc_realloc(wbconn, wbconn->partial.data,
- uint8_t, packet_length);
+ wbconn->partial.data =
+ talloc_realloc(wbconn, wbconn->partial.data, uint8_t,
+ packet_length);
if (!wbconn->partial.data) goto nomem;
wbconn->partial.length = packet_length;
call->event_ctx = conn->event.ctx;
/*
- * we have parsed the request, so we can reset the wbconn->partial_read,
- * maybe we could also free wbconn->partial, but for now we keep it,
- * and overwrite it the next time
+ * we have parsed the request, so we can reset the
+ * wbconn->partial_read, maybe we could also free wbconn->partial, but
+ * for now we keep it, and overwrite it the next time
*/
wbconn->partial_read = 0;
.push_reply = wbsrv_samba3_push_reply
};
+static NTSTATUS init_my_domain(TALLOC_CTX *mem_ctx,
+ struct wbsrv_domain **domain)
+{
+ struct wbsrv_domain *result;
+
+ result = talloc_zero(mem_ctx, struct wbsrv_domain);
+ NT_STATUS_HAVE_NO_MEMORY(result);
+
+ result->name = talloc_strdup(result, lp_workgroup());
+ if (result->name == NULL) {
+ talloc_free(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result->sid = secrets_get_domain_sid(result, lp_workgroup());
+ if (result->sid == NULL) {
+ talloc_free(result);
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+
+ result->initialized = False;
+
+ *domain = result;
+ return NT_STATUS_OK;
+}
+
/*
startup the winbind task
*/
stream_setup_socket() call. */
model_ops = process_model_byname("single");
if (!model_ops) {
- task_server_terminate(task, "Can't find 'single' process model_ops");
+ task_server_terminate(task,
+ "Can't find 'single' process model_ops");
return;
}
if (!service) goto nomem;
service->task = task;
+ status = init_my_domain(service, &service->domains);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Could not init my domain: %s\n",
+ nt_errstr(status)));
+ task_server_terminate(task, nt_errstr(status));
+ return;
+ }
+
/* setup the unprivileged samba3 socket */
listen_socket = talloc(service, struct wbsrv_listen_socket);
if (!listen_socket) goto nomem;
listen_socket->ops = &wbsrv_samba3_protocol_ops;
status = stream_setup_socket(task->event_ctx, model_ops,
&wbsrv_ops, "unix",
- listen_socket->socket_path, &port, listen_socket);
+ listen_socket->socket_path, &port,
+ listen_socket);
if (!NT_STATUS_IS_OK(status)) goto listen_failed;
/* setup the privileged samba3 socket */
listen_socket = talloc(service, struct wbsrv_listen_socket);
if (!listen_socket) goto nomem;
- listen_socket->socket_path = smbd_tmp_path(listen_socket, WINBINDD_SAMBA3_PRIVILEGED_SOCKET);
+ listen_socket->socket_path =
+ smbd_tmp_path(listen_socket,
+ WINBINDD_SAMBA3_PRIVILEGED_SOCKET);
if (!listen_socket->socket_path) goto nomem;
listen_socket->service = service;
listen_socket->privileged = True;
listen_socket->ops = &wbsrv_samba3_protocol_ops;
status = stream_setup_socket(task->event_ctx, model_ops,
&wbsrv_ops, "unix",
- listen_socket->socket_path, &port, listen_socket);
+ listen_socket->socket_path, &port,
+ listen_socket);
if (!NT_STATUS_IS_OK(status)) goto listen_failed;
return;
/*
initialise the winbind server
*/
-static NTSTATUS winbind_init(struct event_context *event_ctx, const struct model_ops *model_ops)
+static NTSTATUS winbind_init(struct event_context *event_ctx,
+ const struct model_ops *model_ops)
{
return task_server_startup(event_ctx, model_ops, winbind_task_init);
}
/* this struct stores global data for the winbind task */
struct wbsrv_service {
struct task_server *task;
- struct dcerpc_pipe *netlogon_pipe;
+
+ struct wbsrv_domain *domains;
+};
+
+struct wbsrv_samconn {
+ struct wbsrv_domain *domain;
+ void *private_data;
+
+ struct composite_context (*seqnum_send)(struct wbsrv_samconn *);
+ NTSTATUS (*seqnum_recv)(struct composite_context *, uint64_t *);
+};
+
+struct wbsrv_domain {
+ struct wbsrv_domain *next, *prev;
+
+ BOOL initialized;
+
+ const char *name;
+ const struct dom_sid *sid;
+
struct dcerpc_pipe *lsa_pipe;
+ struct policy_handle *lsa_policy;
+
+ struct dcerpc_pipe *netlogon_auth2_pipe;
+ struct dcerpc_pipe *netlogon_pipe;
+ struct cli_credentials *schannel_creds;
};
/*