diff options
author | Andrew Bartlett <abartlet@samba.org> | 2008-07-31 07:48:16 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2008-07-31 07:48:16 +1000 |
commit | 337752cfd82dc3dbdf918fd45eddd1aa8fb04576 (patch) | |
tree | 79aa04fbf294add814fb060f73a1909733b18ec4 | |
parent | 2a0677e514b5b9f91d32339077cc7e4187525c3b (diff) | |
parent | e45c3e127d389a2cb63879ca12bbbfed048f4eb1 (diff) | |
download | samba-337752cfd82dc3dbdf918fd45eddd1aa8fb04576.tar.gz samba-337752cfd82dc3dbdf918fd45eddd1aa8fb04576.tar.bz2 samba-337752cfd82dc3dbdf918fd45eddd1aa8fb04576.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-local
(This used to be commit 15d0951b74b46763024560f9cd012338473c5bc3)
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 12 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 1 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 5 | ||||
-rw-r--r-- | source4/libcli/smb2/connect.c | 8 | ||||
-rw-r--r-- | source4/libcli/smb2/logoff.c | 2 | ||||
-rw-r--r-- | source4/libcli/smb2/session.c | 10 | ||||
-rw-r--r-- | source4/libcli/smb2/signing.c | 9 | ||||
-rw-r--r-- | source4/libcli/smb2/smb2.h | 9 | ||||
-rw-r--r-- | source4/libcli/smb2/transport.c | 6 | ||||
-rw-r--r-- | source4/rpc_server/dcerpc_server.c | 1 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision.py | 36 | ||||
-rw-r--r-- | source4/smb_server/smb2/negprot.c | 2 | ||||
-rw-r--r-- | source4/smb_server/smb2/receive.c | 21 | ||||
-rw-r--r-- | source4/smb_server/smb2/sesssetup.c | 34 | ||||
-rw-r--r-- | source4/smb_server/smb_server.h | 7 | ||||
-rw-r--r-- | source4/torture/smb2/connect.c | 11 |
16 files changed, 101 insertions, 73 deletions
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index c4c58398c3..1a2d5faddd 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -392,7 +392,17 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred, return ret; } - /* transfer the enctypes from the smb_krb5_context to the gssapi layer */ + /* + * transfer the enctypes from the smb_krb5_context to the gssapi layer + * + * We use 'our' smb_krb5_context to do the AS-REQ and it is possible + * to configure the enctypes via the krb5.conf. + * + * And the gss_init_sec_context() creates it's own krb5_context and + * the TGS-REQ had all enctypes in it and only the ones configured + * and used for the AS-REQ, so it wasn't possible to disable the usage + * of AES keys. + */ min_stat = krb5_get_default_in_tkt_etypes(ccache->smb_krb5_context->krb5_context, &etypes); if (min_stat == 0) { diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 2acc5c0af4..87ada855d3 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -150,7 +150,6 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req) static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req) { - WERROR status; struct ldb_dn *schema_dn; struct dsdb_schema *schema; char *error_string = NULL; diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 9b8959466d..85fdbe9e87 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -566,9 +566,10 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return WERR_NOMEM; } for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { + char *oid; (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16; - (*prefixes)[i].oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid); - (*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, "."); + oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid); + (*prefixes)[i].oid = talloc_asprintf_append(oid, "."); (*prefixes)[i].oid_len = strlen(blob->ctr.dsdb.mappings[i].oid.oid); } diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index cdb5e3b5d4..c89c109b72 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -112,19 +112,19 @@ static void continue_negprot(struct smb2_request *req) composite_error(c, NT_STATUS_ACCESS_DENIED); return; } - transport->signing.doing_signing = false; + transport->signing_required = false; break; case SMB_SIGNING_SUPPORTED: case SMB_SIGNING_AUTO: if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { - transport->signing.doing_signing = true; + transport->signing_required = true; } else { - transport->signing.doing_signing = false; + transport->signing_required = false; } break; case SMB_SIGNING_REQUIRED: if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) { - transport->signing.doing_signing = true; + transport->signing_required = true; } else { composite_error(c, NT_STATUS_ACCESS_DENIED); return; diff --git a/source4/libcli/smb2/logoff.c b/source4/libcli/smb2/logoff.c index b38a08ca43..e3f83f27d8 100644 --- a/source4/libcli/smb2/logoff.c +++ b/source4/libcli/smb2/logoff.c @@ -33,6 +33,8 @@ struct smb2_request *smb2_logoff_send(struct smb2_session *session) req = smb2_request_init(session->transport, SMB2_OP_LOGOFF, 0x04, false, 0); if (req == NULL) return NULL; + req->session = session; + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid); SSVAL(req->out.body, 0x02, 0); diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 91616319d5..31b3e942e9 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -187,14 +187,14 @@ static void session_request_handler(struct smb2_request *req) return; } - if (session->transport->signing.doing_signing) { - if (session->session_key.length != 16) { - DEBUG(2,("Wrong session key length %u for SMB2 signing\n", + if (session->transport->signing_required) { + if (session->session_key.length == 0) { + DEBUG(0,("Wrong session key length %u for SMB2 signing\n", (unsigned)session->session_key.length)); composite_error(c, NT_STATUS_ACCESS_DENIED); return; } - session->transport->signing.signing_started = true; + session->signing_active = true; } composite_done(c); @@ -218,7 +218,7 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se ZERO_STRUCT(state->io); state->io.in.vc_number = 0; - if (session->transport->signing.doing_signing) { + if (session->transport->signing_required) { state->io.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; } diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index fb2c22db4e..0d655d1a86 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -46,7 +46,7 @@ NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_ke return NT_STATUS_OK; } - if (session_key.length != 16) { + if (session_key.length == 0) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; @@ -57,10 +57,9 @@ NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_ke SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); ZERO_STRUCT(m); - hmac_sha256_init(session_key.data, 16, &m); + hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); hmac_sha256_update(buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); - DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE)); memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16); @@ -95,7 +94,7 @@ NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session return NT_STATUS_OK; } - if (session_key.length != 16) { + if (session_key.length == 0) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; @@ -106,7 +105,7 @@ NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); ZERO_STRUCT(m); - hmac_sha256_init(session_key.data, 16, &m); + hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); hmac_sha256_update(buf->hdr, buf->size-NBT_HDR_SIZE, &m); hmac_sha256_final(res, &m); diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 2b468d3dc9..5d6341a15b 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -27,11 +27,6 @@ struct smb2_handle; -struct smb2_signing_context { - bool doing_signing; - bool signing_started; -}; - /* information returned from the negotiate process */ @@ -78,7 +73,8 @@ struct smb2_transport { } oplock; struct smbcli_options options; - struct smb2_signing_context signing; + + bool signing_required; }; @@ -98,6 +94,7 @@ struct smb2_session { struct gensec_security *gensec; uint64_t uid; DATA_BLOB session_key; + bool signing_active; }; diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index 6e0d523e21..d9691bec7c 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -235,7 +235,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); req->status = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS)); - if (req->session && transport->signing.doing_signing) { + if (req->session && req->session->signing_active) { status = smb2_check_signature(&req->in, req->session->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -352,9 +352,7 @@ void smb2_transport_send(struct smb2_request *req) } /* possibly sign the message */ - if (req->transport->signing.doing_signing && - req->transport->signing.signing_started && - req->session) { + if (req->session && req->session->signing_active) { status = smb2_sign_message(&req->out, req->session->session_key); if (!NT_STATUS_IS_OK(status)) { req->state = SMB2_REQUEST_ERROR; diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index cb07f6e8ce..95589498e2 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -947,7 +947,6 @@ _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) uint32_t length; struct data_blob_list_item *rep; struct ncacn_packet pkt; - const uint32_t overhead = (DCERPC_MAX_SIGN_SIZE+DCERPC_RESPONSE_LENGTH); rep = talloc(call, struct data_blob_list_item); NT_STATUS_HAVE_NO_MEMORY(rep); diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 0119f40c7f..441d662b23 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -133,26 +133,6 @@ findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2] findnss_gid = lambda names: findnss(grp.getgrnam, names)[2] -def open_ldb(session_info, credentials, lp, dbname): - """Open a LDB, thrashing it if it is corrupt. - - :param session_info: auth session information - :param credentials: credentials - :param lp: Loadparm context - :param dbname: Path of the database to open. - :return: a Ldb object - """ - assert session_info is not None - try: - return Ldb(dbname, session_info=session_info, credentials=credentials, - lp=lp) - except LdbError, e: - print e - os.unlink(dbname) - return Ldb(dbname, session_info=session_info, credentials=credentials, - lp=lp) - - def read_and_sub_file(file, subst_vars): """Read a file and sub in variables found in it @@ -799,7 +779,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), { "CONFIGDN": names.configdn, "ACI": aci, - "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb", }) message("Modifying configuration container") setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), { @@ -811,7 +790,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), { "SCHEMADN": names.schemadn, "ACI": aci, - "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" }) message("Modifying schema container") @@ -1195,7 +1173,7 @@ def provision_backend(setup_dir=None, message=None, paths = provision_paths_from_lp(lp, names.dnsdomain) if not os.path.isdir(paths.ldapdir): - os.makedirs(paths.ldapdir) + os.makedirs(paths.ldapdir, 0700) schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb") try: os.unlink(schemadb_path) @@ -1209,7 +1187,6 @@ def provision_backend(setup_dir=None, message=None, setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"), {"SCHEMADN": names.schemadn, "ACI": "#", - "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" }) setup_modify_ldif(schemadb, setup_path("provision_schema_basedn_modify.ldif"), \ @@ -1252,6 +1229,8 @@ def provision_backend(setup_dir=None, message=None, slapdcommand="Initailise Fedora DS with: setup-ds.pl --file=%s" % paths.fedoradsinf + ldapuser = "--simple-bind-dn=" + names.ldapmanagerdn + elif ldap_backend_type == "openldap": attrs = ["linkID", "lDAPDisplayName"] res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs) @@ -1290,7 +1269,7 @@ def provision_backend(setup_dir=None, message=None, setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema")) if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")): - os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")) + os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"), 0700) setup_file(setup_path("cn=samba.ldif"), os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"), @@ -1310,7 +1289,10 @@ def provision_backend(setup_dir=None, message=None, server_port_string = " -h ldap://0.0.0.0:%d" % ldap_backend_port else: server_port_string = "" - slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string + + slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string + + ldapuser = "--username=samba-admin" schema_command = "bin/ad2oLschema --option=convert:target=" + ldap_backend_type + " -I " + setup_path(mapping) + " -H tdb://" + schemadb_path + " -O " + os.path.join(paths.ldapdir, backend_schema) @@ -1330,7 +1312,7 @@ def provision_backend(setup_dir=None, message=None, message("LDAP admin password: %s" % adminpass) message(slapdcommand) - + message("Run provision with: --ldap-backend=ldapi --ldap-backend-type=" + ldap_backend_type + " --password=" + adminpass + " " + ldapuser) def create_phpldapadmin_config(path, setup_path, ldapi_uri): """Create a PHP LDAP admin configuration file. diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 3e6e2e1a43..d64b36d659 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -122,7 +122,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 case SMB_SIGNING_REQUIRED: io->out.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED; /* force signing on immediately */ - req->smb_conn->doing_signing = true; + req->smb_conn->smb2_signing_required = true; break; } io->out.dialect_revision = SMB2_DIALECT_REVISION; diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 2f4e9df2b6..cfd6c1d01a 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -235,11 +235,8 @@ void smb2srv_send_reply(struct smb2srv_request *req) _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } - /* if the request was signed or doing_signing is true, then we - must sign the reply */ - if (req->session && - (req->smb_conn->doing_signing || - (IVAL(req->in.hdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_SIGNED))) { + /* if signing is active on the session then sign the packet */ + if (req->session && req->session->smb2_signing.active) { status = smb2_sign_message(&req->out, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -310,18 +307,22 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) should give a signed reply to any signed request */ if (flags & SMB2_HDR_FLAG_SIGNED) { NTSTATUS status; - if (req->session == NULL) { - /* we can't check signing with no session */ - smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); - return NT_STATUS_OK; + + if (!req->session) goto nosession; + + if (!req->session->smb2_signing.active) { + /* TODO: workout the correct error code */ + smb2srv_send_error(req, NT_STATUS_FOOBAR); + return NT_STATUS_OK; } + status = smb2_check_signature(&req->in, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { smb2srv_send_error(req, status); return NT_STATUS_OK; } - } else if (req->smb_conn->doing_signing && req->session != NULL) { + } else if (req->session && req->session->smb2_signing.active) { /* we require signing and this request was not signed */ smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); return NT_STATUS_OK; diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c index 9fb3220005..9f8765d6e9 100644 --- a/source4/smb_server/smb2/sesssetup.c +++ b/source4/smb_server/smb2/sesssetup.c @@ -90,6 +90,10 @@ static void smb2srv_sesssetup_callback(struct gensec_update_request *greq, void } req->session = smb_sess; + if (smb_sess->smb2_signing.required) { + /* activate smb2 signing on the session */ + smb_sess->smb2_signing.active = true; + } done: io->smb2.out.uid = smb_sess->vuid; failed: @@ -182,7 +186,15 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses This is deliberate as windows does not set it even when it does set SMB2_NEGOTIATE_SIGNING_REQUIRED */ if (io->smb2.in.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) { - req->smb_conn->doing_signing = true; + smb_sess->smb2_signing.required = true; + } else if (req->smb_conn->smb2_signing_required) { + /* + * if required signing was negotiates in SMB2 Negotiate + * then the client made an error not using it here + */ + DEBUG(1, ("SMB2 signing required on the connection but not used on session\n")); + req->status = NT_STATUS_FOOBAR; + goto failed; } return; @@ -212,11 +224,25 @@ void smb2srv_sesssetup_recv(struct smb2srv_request *req) smb2srv_sesssetup_backend(req, io); } -static NTSTATUS smb2srv_logoff_backend(struct smb2srv_request *req) +static int smb2srv_cleanup_session_destructor(struct smbsrv_session **session) { /* TODO: call ntvfs backends to close file of this session */ - talloc_free(req->session); - req->session = NULL; + DEBUG(0,("free session[%p]\n", *session)); + talloc_free(*session); + return 0; +} + +static NTSTATUS smb2srv_logoff_backend(struct smb2srv_request *req) +{ + struct smbsrv_session **session_ptr; + + /* we need to destroy the session after sending the reply */ + session_ptr = talloc(req, struct smbsrv_session *); + NT_STATUS_HAVE_NO_MEMORY(session_ptr); + + *session_ptr = req->session; + talloc_set_destructor(session_ptr, smb2srv_cleanup_session_destructor); + return NT_STATUS_OK; } diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index dd4ec3281b..4676fc3e9c 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -100,6 +100,11 @@ struct smbsrv_session { struct auth_session_info *session_info; + struct { + bool required; + bool active; + } smb2_signing; + /* some statistics for the management tools */ struct { /* the time when the session setup started */ @@ -380,7 +385,7 @@ struct smbsrv_connection { struct loadparm_context *lp_ctx; - bool doing_signing; + bool smb2_signing_required; }; struct model_ops; diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c index 826bb2d719..e77e32ff7a 100644 --- a/source4/torture/smb2/connect.c +++ b/source4/torture/smb2/connect.c @@ -193,6 +193,7 @@ bool torture_smb2_connect(struct torture_context *torture) { TALLOC_CTX *mem_ctx = talloc_new(NULL); struct smb2_tree *tree; + struct smb2_request *req; struct smb2_handle h1, h2; NTSTATUS status; @@ -242,7 +243,15 @@ bool torture_smb2_connect(struct torture_context *torture) return false; } - status = smb2_logoff(tree->session); + req = smb2_logoff_send(tree->session); + if (!req) { + printf("smb2_logoff_send() failed\n"); + return false; + } + + req->session = NULL; + + status = smb2_logoff_recv(req); if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) { printf("Logoff should have disabled session - %s\n", nt_errstr(status)); return false; |