diff options
59 files changed, 1077 insertions, 967 deletions
diff --git a/source4/cluster/ctdb/opendb_ctdb.c b/source4/cluster/ctdb/opendb_ctdb.c index ed09cf0bbc..b1faf9e0e6 100644 --- a/source4/cluster/ctdb/opendb_ctdb.c +++ b/source4/cluster/ctdb/opendb_ctdb.c @@ -283,7 +283,8 @@ static NTSTATUS odb_oplock_break_send(struct odb_context *odb, struct opendb_ent */ static NTSTATUS odb_ctdb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - int *fd, bool allow_level_II_oplock, + int *fd, NTTIME open_write_time, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { @@ -492,37 +493,30 @@ static NTSTATUS odb_ctdb_set_delete_on_close(struct odb_lock *lck, bool del_on_c return odb_push_record(lck, &file); } +static NTSTATUS odb_ctdb_set_write_time(struct odb_lock *lck, + NTTIME write_time, bool force) +{ + /* + * as this file will went away and isn't used yet, + * copy the implementation from the tdb backend + * --metze + */ + return NT_STATUS_FOOBAR; +} + /* return the current value of the delete_on_close bit, and how many people still have the file open */ -static NTSTATUS odb_ctdb_get_delete_on_close(struct odb_context *odb, - DATA_BLOB *key, bool *del_on_close) +static NTSTATUS odb_ctdb_get_file_infos(struct odb_context *odb, DATA_BLOB *key, + bool *del_on_close, NTTIME *write_time) { - NTSTATUS status; - struct opendb_file file; - struct odb_lock *lck; - - (*del_on_close) = false; - - lck = odb_lock(odb, odb, key); - NT_STATUS_HAVE_NO_MEMORY(lck); - - status = odb_pull_record(lck, &file); - if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) { - talloc_free(lck); - return NT_STATUS_OK; - } - if (!NT_STATUS_IS_OK(status)) { - talloc_free(lck); - return status; - } - - (*del_on_close) = file.delete_on_close; - - talloc_free(lck); - - return NT_STATUS_OK; + /* + * as this file will went away and isn't used yet, + * copy the implementation from the tdb backend + * --metze + */ + return NT_STATUS_FOOBAR; } @@ -589,7 +583,8 @@ static const struct opendb_ops opendb_ctdb_ops = { .odb_rename = odb_ctdb_rename, .odb_get_path = odb_ctdb_get_path, .odb_set_delete_on_close = odb_ctdb_set_delete_on_close, - .odb_get_delete_on_close = odb_ctdb_get_delete_on_close, + .odb_set_write_time = odb_ctdb_set_write_time, + .odb_get_file_infos = odb_ctdb_get_file_infos, .odb_can_open = odb_ctdb_can_open, .odb_update_oplock = odb_ctdb_update_oplock, .odb_break_oplocks = odb_ctdb_break_oplocks diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 9c7b1f6457..70e578ee0d 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -34,10 +34,7 @@ #include "includes.h" #include "system/time.h" -#include "kdc.h" #include "dsdb/common/flags.h" -#include "hdb.h" -#include "krb5_locl.h" #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" #include "librpc/gen_ndr/netlogon.h" @@ -51,6 +48,7 @@ #include "libcli/auth/libcli_auth.h" #include "param/param.h" #include "events/events.h" +#include "kdc/kdc.h" enum hdb_ldb_ent_type { HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER, diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index 84d9d45f57..dfd62c55a4 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -28,17 +28,14 @@ #include "smbd/process_model.h" #include "lib/events/events.h" #include "lib/socket/socket.h" -#include "kdc/kdc.h" #include "system/network.h" #include "lib/util/dlinklist.h" #include "lib/messaging/irpc.h" #include "lib/stream/packet.h" #include "librpc/gen_ndr/samr.h" #include "lib/socket/netif.h" -#include "heimdal/kdc/windc_plugin.h" -#include "heimdal/lib/krb5/krb5_locl.h" -#include "heimdal/kdc/kdc_locl.h" #include "param/param.h" +#include "kdc/kdc.h" /* Disgusting hack to get a mem_ctx and lp_ctx into the hdb plugin, when diff --git a/source4/kdc/kdc.h b/source4/kdc/kdc.h index 9be15115d1..0943de4b00 100644 --- a/source4/kdc/kdc.h +++ b/source4/kdc/kdc.h @@ -24,6 +24,7 @@ #include "auth/kerberos/kerberos.h" #include "heimdal/kdc/kdc.h" #include "heimdal/lib/hdb/hdb.h" +#include "heimdal/kdc/windc_plugin.h" #include "kdc/pac_glue.h" struct kdc_server; diff --git a/source4/kdc/kpasswdd.c b/source4/kdc/kpasswdd.c index 1d49a8a4bd..b42769c6dc 100644 --- a/source4/kdc/kpasswdd.c +++ b/source4/kdc/kpasswdd.c @@ -24,7 +24,6 @@ #include "smbd/service_task.h" #include "lib/events/events.h" #include "lib/socket/socket.h" -#include "kdc/kdc.h" #include "system/network.h" #include "lib/util/dlinklist.h" #include "lib/ldb/include/ldb.h" @@ -39,6 +38,7 @@ #include "rpc_server/samr/proto.h" #include "libcli/security/security.h" #include "param/param.h" +#include "kdc/kdc.h" /* hold information about one kdc socket */ struct kpasswd_socket { diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 1c68d4c37d..cab1446ff3 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -21,7 +21,6 @@ */ #include "includes.h" -#include "kdc/kdc.h" #include "dsdb/common/flags.h" #include "lib/ldb/include/ldb.h" #include "librpc/gen_ndr/ndr_krb5pac.h" @@ -30,6 +29,7 @@ #include "auth/auth_sam.h" #include "auth/auth_sam_reply.h" #include "param/param.h" +#include "kdc/kdc.h" struct krb5_dh_moduli; struct _krb5_krb_auth_data; diff --git a/source4/lib/crypto/config.mk b/source4/lib/crypto/config.mk index b9a7f7cb9e..ee111bd088 100644 --- a/source4/lib/crypto/config.mk +++ b/source4/lib/crypto/config.mk @@ -6,14 +6,13 @@ LIBCRYPTO_OBJ_FILES = $(addprefix $(libcryptosrcdir)/, \ crc32.o md5.o hmacmd5.o md4.o \ - arcfour.o sha1.o hmacsha1.o) - + arcfour.o sha256.o hmacsha256.o) [MODULE::TORTURE_LIBCRYPTO] SUBSYSTEM = smbtorture PRIVATE_DEPENDENCIES = LIBCRYPTO TORTURE_LIBCRYPTO_OBJ_FILES = $(addprefix $(libcryptosrcdir)/, \ - md4test.o md5test.o hmacmd5test.o sha1test.o hmacsha1test.o) + md4test.o md5test.o hmacmd5test.o) $(eval $(call proto_header_template,$(libcryptosrcdir)/test_proto.h,$(TORTURE_LIBCRYPTO_OBJ_FILES:.o=.c))) diff --git a/source4/lib/crypto/crypto.h b/source4/lib/crypto/crypto.h index 10e2258fa7..fc283f72ba 100644 --- a/source4/lib/crypto/crypto.h +++ b/source4/lib/crypto/crypto.h @@ -21,8 +21,8 @@ #include "lib/crypto/md4.h" #include "lib/crypto/md5.h" #include "lib/crypto/hmacmd5.h" -#include "lib/crypto/sha1.h" -#include "lib/crypto/hmacsha1.h" +#include "lib/crypto/sha256.h" +#include "lib/crypto/hmacsha256.h" struct arcfour_state { uint8_t sbox[256]; diff --git a/source4/lib/crypto/hmacsha1test.c b/source4/lib/crypto/hmacsha1test.c deleted file mode 100644 index 6e53124d21..0000000000 --- a/source4/lib/crypto/hmacsha1test.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - Unix SMB/CIFS implementation. - HMAC SHA-1 tests - Copyright (C) Stefan Metzmacher - - 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 3 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, see <http://www.gnu.org/licenses/>. -*/ -#include "includes.h" -#include "lib/crypto/crypto.h" - -struct torture_context; - -static DATA_BLOB data_blob_repeat_byte(uint8_t byte, size_t length) -{ - DATA_BLOB b = data_blob(NULL, length); - memset(b.data, byte, length); - return b; -} - -/* - This uses the test values from rfc2202 -*/ -bool torture_local_crypto_hmacsha1(struct torture_context *torture) -{ - bool ret = true; - uint32_t i; - struct { - DATA_BLOB key; - DATA_BLOB data; - DATA_BLOB sha1; - } testarray[7]; - - testarray[0].key = data_blob_repeat_byte(0x0b, 20); - testarray[0].data = data_blob_string_const("Hi There"); - testarray[0].sha1 = strhex_to_data_blob("b617318655057264e28bc0b6fb378c8ef146be00"); - - testarray[1].key = data_blob_string_const("Jefe"); - testarray[1].data = data_blob_string_const("what do ya want for nothing?"); - testarray[1].sha1 = strhex_to_data_blob("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); - - testarray[2].key = data_blob_repeat_byte(0xaa, 20); - testarray[2].data = data_blob_repeat_byte(0xdd, 50); - testarray[2].sha1 = strhex_to_data_blob("125d7342b9ac11cd91a39af48aa17b4f63f175d3"); - - testarray[3].key = strhex_to_data_blob("0102030405060708090a0b0c0d0e0f10111213141516171819"); - testarray[3].data = data_blob_repeat_byte(0xcd, 50); - testarray[3].sha1 = strhex_to_data_blob("4c9007f4026250c6bc8414f9bf50c86c2d7235da"); - - testarray[4].key = data_blob_repeat_byte(0x0c, 20); - testarray[4].data = data_blob_string_const("Test With Truncation"); - testarray[4].sha1 = strhex_to_data_blob("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"); - /* sha1-96 = 0x4c1a03424b55e07fe7f27be1 */ - - testarray[5].key = data_blob_repeat_byte(0xaa, 80); - testarray[5].data = data_blob_string_const("Test Using Larger Than Block-Size Key - Hash Key First"); - testarray[5].sha1 = strhex_to_data_blob("aa4ae5e15272d00e95705637ce8a3b55ed402112"); - - testarray[6].key = data_blob_repeat_byte(0xaa, 80); - testarray[6].data = data_blob_string_const("Test Using Larger Than Block-Size Key " - "and Larger Than One Block-Size Data"); - testarray[6].sha1 = strhex_to_data_blob("e8e99d0f45237d786d6bbaa7965c7808bbff1a91"); - - for (i=0; i < ARRAY_SIZE(testarray); i++) { - struct HMACSHA1Context ctx; - uint8_t sha1[SHA1HashSize]; - int e; - - hmac_sha1_init(testarray[i].key.data, testarray[i].key.length, &ctx); - hmac_sha1_update(testarray[i].data.data, testarray[i].data.length, &ctx); - hmac_sha1_final(sha1, &ctx); - - e = memcmp(testarray[i].sha1.data, - sha1, - MIN(testarray[i].sha1.length, sizeof(sha1))); - if (e != 0) { - printf("hmacsha1 test[%u]: failed\n", i); - dump_data(0, testarray[i].key.data, testarray[i].key.length); - dump_data(0, testarray[i].data.data, testarray[i].data.length); - dump_data(0, testarray[i].sha1.data, testarray[i].sha1.length); - dump_data(0, sha1, sizeof(sha1)); - ret = false; - } - } - - return ret; -} diff --git a/source4/lib/crypto/hmacsha1.c b/source4/lib/crypto/hmacsha256.c index 21ce966f60..6b0af9ee83 100644 --- a/source4/lib/crypto/hmacsha1.c +++ b/source4/lib/crypto/hmacsha256.c @@ -1,7 +1,12 @@ /* Unix SMB/CIFS implementation. - Interface header: HMAC SHA-1 code - Copyright (C) Stefan Metzmacher + + Interface header: HMAC SHA-256 code + + Copyright (C) Andrew Tridgell 2008 + + based in hmacsha1.c which is: + Copyright (C) Stefan Metzmacher 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 @@ -25,24 +30,24 @@ #include "lib/crypto/crypto.h" /*********************************************************************** - the rfc 2104/2202 version of hmac_sha1 initialisation. + the rfc 2104/2202 version of hmac_sha256 initialisation. ***********************************************************************/ -_PUBLIC_ void hmac_sha1_init(const uint8_t *key, size_t key_len, struct HMACSHA1Context *ctx) +_PUBLIC_ void hmac_sha256_init(const uint8_t *key, size_t key_len, struct HMACSHA256Context *ctx) { int i; - uint8_t tk[SHA1HashSize]; + uint8_t tk[SHA256_DIGEST_LENGTH]; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ + /* if key is longer than 64 bytes reset it to key=HASH(key) */ if (key_len > 64) { - struct SHA1Context tctx; + SHA256_CTX tctx; - SHA1Init(&tctx); - SHA1Update(&tctx, key, key_len); - SHA1Final(tk, &tctx); + SHA256_Init(&tctx); + SHA256_Update(&tctx, key, key_len); + SHA256_Final(tk, &tctx); key = tk; - key_len = SHA1HashSize; + key_len = SHA256_DIGEST_LENGTH; } /* start out by storing key in pads */ @@ -58,29 +63,29 @@ _PUBLIC_ void hmac_sha1_init(const uint8_t *key, size_t key_len, struct HMACSHA1 ctx->k_opad[i] ^= 0x5c; } - SHA1Init(&ctx->ctx); - SHA1Update(&ctx->ctx, ctx->k_ipad, 64); + SHA256_Init(&ctx->ctx); + SHA256_Update(&ctx->ctx, ctx->k_ipad, 64); } /*********************************************************************** - update hmac_sha1 "inner" buffer + update hmac_sha256 "inner" buffer ***********************************************************************/ -_PUBLIC_ void hmac_sha1_update(const uint8_t *data, size_t data_len, struct HMACSHA1Context *ctx) +_PUBLIC_ void hmac_sha256_update(const uint8_t *data, size_t data_len, struct HMACSHA256Context *ctx) { - SHA1Update(&ctx->ctx, data, data_len); /* then text of datagram */ + SHA256_Update(&ctx->ctx, data, data_len); /* then text of datagram */ } /*********************************************************************** - finish off hmac_sha1 "inner" buffer and generate outer one. + finish off hmac_sha256 "inner" buffer and generate outer one. ***********************************************************************/ -_PUBLIC_ void hmac_sha1_final(uint8_t digest[SHA1HashSize], struct HMACSHA1Context *ctx) +_PUBLIC_ void hmac_sha256_final(uint8_t digest[SHA256_DIGEST_LENGTH], struct HMACSHA256Context *ctx) { - struct SHA1Context ctx_o; + SHA256_CTX ctx_o; - SHA1Final(digest, &ctx->ctx); + SHA256_Final(digest, &ctx->ctx); - SHA1Init(&ctx_o); - SHA1Update(&ctx_o, ctx->k_opad, 64); - SHA1Update(&ctx_o, digest, SHA1HashSize); - SHA1Final(digest, &ctx_o); + SHA256_Init(&ctx_o); + SHA256_Update(&ctx_o, ctx->k_opad, 64); + SHA256_Update(&ctx_o, digest, SHA256_DIGEST_LENGTH); + SHA256_Final(digest, &ctx_o); } diff --git a/source4/lib/crypto/hmacsha1.h b/source4/lib/crypto/hmacsha256.h index 0638c66d53..8960c636c1 100644 --- a/source4/lib/crypto/hmacsha1.h +++ b/source4/lib/crypto/hmacsha256.h @@ -1,7 +1,13 @@ /* Unix SMB/CIFS implementation. - Interface header: HMAC SHA1 code - Copyright (C) Stefan Metzmacher 2006 + + Interface header: HMAC SHA256 code + + Copyright (C) Andrew Tridgell 2008 + + based on hmacsha1.h which is: + + Copyright (C) Stefan Metzmacher 2006 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 @@ -17,17 +23,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _HMAC_SHA1_H +#ifndef _HMAC_SHA256_H -struct HMACSHA1Context { - struct SHA1Context ctx; +struct HMACSHA256Context { + SHA256_CTX ctx; uint8_t k_ipad[65]; uint8_t k_opad[65]; - }; -void hmac_sha1_init(const uint8_t *key, size_t key_len, struct HMACSHA1Context *ctx); -void hmac_sha1_update(const uint8_t *data, size_t data_len, struct HMACSHA1Context *ctx); -void hmac_sha1_final(uint8_t digest[20], struct HMACSHA1Context *ctx); +void hmac_sha256_init(const uint8_t *key, size_t key_len, struct HMACSHA256Context *ctx); +void hmac_sha256_update(const uint8_t *data, size_t data_len, struct HMACSHA256Context *ctx); +void hmac_sha256_final(uint8_t digest[20], struct HMACSHA256Context *ctx); -#endif /* _HMAC_SHA1_H */ +#endif /* _HMAC_SHA256_H */ diff --git a/source4/lib/crypto/sha1.c b/source4/lib/crypto/sha1.c deleted file mode 100644 index 1b91f8a949..0000000000 --- a/source4/lib/crypto/sha1.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - This file contains the reference implementation of SHA-1 - from http://www.ietf.org/rfc/rfc3174.txt -*/ -/* - * sha1.c - * - * Description: - * This file implements the Secure Hashing Algorithm 1 as - * defined in FIPS PUB 180-1 published April 17, 1995. - * - * The SHA-1, produces a 160-bit message digest for a given - * data stream. It should take about 2**n steps to find a - * message with the same digest as a given message and - * 2**(n/2) to find any two messages with the same digest, - * when n is the digest size in bits. Therefore, this - * algorithm can serve as a means of providing a - * "fingerprint" for a message. - * - * Portability Issues: - * SHA-1 is defined in terms of 32-bit "words". This code - * uses <stdint.h> (included via "sha1.h" to define 32 and 8 - * bit unsigned integer types. If your C compiler does not - * support 32 bit unsigned integers, this code is not - * appropriate. - * - * Caveats: - * SHA-1 is designed to work with messages less than 2^64 bits - * long. Although SHA-1 allows a message digest to be generated - * for messages of any number of bits less than 2^64, this - * implementation only works with messages with a length that is - * a multiple of the size of an 8-bit character. - * - */ - -#include "includes.h" - -#include "sha1.h" - -/* - * Define the SHA1 circular left shift macro - */ -#define SHA1CircularShift(bits,word) \ - (((word) << (bits)) | ((word) >> (32-(bits)))) - -/* Local Function Prototyptes */ -static void SHA1PadMessage(struct SHA1Context *); -static void SHA1ProcessMessageBlock(struct SHA1Context *); - -/* - * SHA1Init (SHA1Reset in the rfc) - * - * Description: - * This function will initialize the SHA1Context in preparation - * for computing a new SHA1 message digest. - * - * Parameters: - * context: [in/out] - * The context to reset. - * - * Returns: - * sha Error Code. - * - */ -int SHA1Init(struct SHA1Context *context) -{ - if (!context) - { - return shaNull; - } - - context->Length_Low = 0; - context->Length_High = 0; - context->Message_Block_Index = 0; - - context->Intermediate_Hash[0] = 0x67452301; - context->Intermediate_Hash[1] = 0xEFCDAB89; - context->Intermediate_Hash[2] = 0x98BADCFE; - context->Intermediate_Hash[3] = 0x10325476; - context->Intermediate_Hash[4] = 0xC3D2E1F0; - - context->Computed = 0; - context->Corrupted = 0; - - return shaSuccess; -} - -/* - * SHA1Final (SHA1Result in the rfc) - * - * Description: - * This function will return the 160-bit message digest into the - * Message_Digest array provided by the caller. - * NOTE: The first octet of hash is stored in the 0th element, - * the last octet of hash in the 19th element. - * - * Parameters: - * context: [in/out] - * The context to use to calculate the SHA-1 hash. - * Message_Digest: [out] - * Where the digest is returned. - * - * Returns: - * sha Error Code. - * - */ -int SHA1Final(uint8_t Message_Digest[SHA1HashSize], - struct SHA1Context *context) -{ - int i; - - if (!context || !Message_Digest) - { - return shaNull; - } - - if (context->Corrupted) - { - return context->Corrupted; - } - - if (!context->Computed) - { - SHA1PadMessage(context); - for(i=0; i<64; ++i) - { - /* message may be sensitive, clear it out */ - context->Message_Block[i] = 0; - } - context->Length_Low = 0; /* and clear length */ - context->Length_High = 0; - context->Computed = 1; - } - - for(i = 0; i < SHA1HashSize; ++i) - { - Message_Digest[i] = context->Intermediate_Hash[i>>2] - >> 8 * ( 3 - ( i & 0x03 ) ); - } - - return shaSuccess; -} - -/* - * SHA1Update (SHA1Input in the rfc) - * - * Description: - * This function accepts an array of octets as the next portion - * of the message. - * - * Parameters: - * context: [in/out] - * The SHA context to update - * message_array: [in] - * An array of characters representing the next portion of - * the message. - * length: [in] - * The length of the message in message_array - * - * Returns: - * sha Error Code. - * - */ -int SHA1Update(struct SHA1Context *context, - const uint8_t *message_array, - size_t length) -{ - if (!length) - { - return shaSuccess; - } - - if (!context || !message_array) - { - return shaNull; - } - - if (context->Computed) - { - context->Corrupted = shaStateError; - return shaStateError; - } - - if (context->Corrupted) - { - return context->Corrupted; - } - while(length-- && !context->Corrupted) - { - context->Message_Block[context->Message_Block_Index++] = - (*message_array & 0xFF); - - context->Length_Low += 8; - if (context->Length_Low == 0) - { - context->Length_High++; - if (context->Length_High == 0) - { - /* Message is too long */ - context->Corrupted = 1; - } - } - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - - message_array++; - } - - return shaSuccess; -} - -/* - * SHA1ProcessMessageBlock - * - * Description: - * This function will process the next 512 bits of the message - * stored in the Message_Block array. - * - * Parameters: - * None. - * - * Returns: - * Nothing. - * - * Comments: - * Many of the variable names in this code, especially the - * single character names, were used because those were the - * names used in the publication. - * - * - */ -static void SHA1ProcessMessageBlock(struct SHA1Context *context) -{ - const uint32_t K[] = { /* Constants defined in SHA-1 */ - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; /* Loop counter */ - uint32_t temp; /* Temporary word value */ - uint32_t W[80]; /* Word sequence */ - uint32_t A, B, C, D, E; /* Word buffers */ - - /* - * Initialize the first 16 words in the array W - */ - for(t = 0; t < 16; t++) - { - W[t] = context->Message_Block[t * 4] << 24; - W[t] |= context->Message_Block[t * 4 + 1] << 16; - W[t] |= context->Message_Block[t * 4 + 2] << 8; - W[t] |= context->Message_Block[t * 4 + 3]; - } - - for(t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = context->Intermediate_Hash[0]; - B = context->Intermediate_Hash[1]; - C = context->Intermediate_Hash[2]; - D = context->Intermediate_Hash[3]; - E = context->Intermediate_Hash[4]; - - for(t = 0; t < 20; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 40; t < 60; t++) - { - temp = SHA1CircularShift(5,A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for(t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - context->Intermediate_Hash[0] += A; - context->Intermediate_Hash[1] += B; - context->Intermediate_Hash[2] += C; - context->Intermediate_Hash[3] += D; - context->Intermediate_Hash[4] += E; - - context->Message_Block_Index = 0; -} - - -/* - * SHA1PadMessage - * - * Description: - * According to the standard, the message must be padded to an even - * 512 bits. The first padding bit must be a '1'. The last 64 - * bits represent the length of the original message. All bits in - * between should be 0. This function will pad the message - * according to those rules by filling the Message_Block array - * accordingly. It will also call the ProcessMessageBlock function - * provided appropriately. When it returns, it can be assumed that - * the message digest has been computed. - * - * Parameters: - * context: [in/out] - * The context to pad - * ProcessMessageBlock: [in] - * The appropriate SHA*ProcessMessageBlock function - * Returns: - * Nothing. - * - */ - -static void SHA1PadMessage(struct SHA1Context *context) -{ - /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second - * block. - */ - if (context->Message_Block_Index > 55) - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 64) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - - SHA1ProcessMessageBlock(context); - - while(context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - else - { - context->Message_Block[context->Message_Block_Index++] = 0x80; - while(context->Message_Block_Index < 56) - { - context->Message_Block[context->Message_Block_Index++] = 0; - } - } - - /* - * Store the message length as the last 8 octets - */ - context->Message_Block[56] = context->Length_High >> 24; - context->Message_Block[57] = context->Length_High >> 16; - context->Message_Block[58] = context->Length_High >> 8; - context->Message_Block[59] = context->Length_High; - context->Message_Block[60] = context->Length_Low >> 24; - context->Message_Block[61] = context->Length_Low >> 16; - context->Message_Block[62] = context->Length_Low >> 8; - context->Message_Block[63] = context->Length_Low; - - SHA1ProcessMessageBlock(context); -} diff --git a/source4/lib/crypto/sha1.h b/source4/lib/crypto/sha1.h deleted file mode 100644 index 4a2d448bfc..0000000000 --- a/source4/lib/crypto/sha1.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file contains the reference implementation of SHA-1 - from http://www.ietf.org/rfc/rfc3174.txt -*/ -/* - * sha1.h - * - * Description: - * This is the header file for code which implements the Secure - * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published - * April 17, 1995. - * - * Many of the variable names in this code, especially the - * single character names, were used because those were the names - * used in the publication. - * - * Please read the file sha1.c for more information. - * - */ -#ifndef _SHA1_H_ -#define _SHA1_H_ - -#ifndef _SHA_enum_ -#define _SHA_enum_ -enum -{ - shaSuccess = 0, - shaNull, /* Null pointer parameter */ - shaInputTooLong, /* input data too long */ - shaStateError /* called Input after Result */ -}; -#endif -#define SHA1HashSize 20 - -/* - * This structure will hold context information for the SHA-1 - * hashing operation - */ -struct SHA1Context -{ - uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ - - uint32_t Length_Low; /* Message length in bits */ - uint32_t Length_High; /* Message length in bits */ - - /* Index into message block array */ - int16_t Message_Block_Index; - uint8_t Message_Block[64]; /* 512-bit message blocks */ - - int Computed; /* Is the digest computed? */ - int Corrupted; /* Is the message digest corrupted? */ -}; - -/* - * Function Prototypes - */ - -int SHA1Init(struct SHA1Context *); -int SHA1Update(struct SHA1Context *, const uint8_t *data, size_t data_len); -int SHA1Final(uint8_t Message_Digest[SHA1HashSize], struct SHA1Context *); - -#endif diff --git a/source4/lib/crypto/sha1test.c b/source4/lib/crypto/sha1test.c deleted file mode 100644 index 7777764277..0000000000 --- a/source4/lib/crypto/sha1test.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file contains the reference implementation of SHA-1 - from http://www.ietf.org/rfc/rfc3174.txt -*/ -/* - * sha1test.c - * - * Description: - * This file will exercise the SHA-1 code performing the three - * tests documented in FIPS PUB 180-1 plus one which calls - * SHA1Input with an exact multiple of 512 bits, plus a few - * error test checks. - * - * Portability Issues: - * None. - * - */ - -#include "includes.h" -#include "torture/torture.h" - -#include "lib/crypto/crypto.h" - -struct torture_context; - -/* - * Define patterns for testing - */ -#define TEST1 "abc" -#define TEST2a "abcdbcdecdefdefgefghfghighijhi" -#define TEST2b "jkijkljklmklmnlmnomnopnopq" -#define TEST2 TEST2a TEST2b -#define TEST3 "a" -#define TEST4a "01234567012345670123456701234567" -#define TEST4b "01234567012345670123456701234567" - /* an exact multiple of 512 bits */ -#define TEST4 TEST4a TEST4b -static const char *testarray[4] = -{ - TEST1, - TEST2, - TEST3, - TEST4 -}; -static int repeatcount[4] = { 1, 1, 1000000, 10 }; -static const char *resultarray[4] = -{ - "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D ", - "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1 ", - "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F ", - "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52 " -}; - - -bool torture_local_crypto_sha1(struct torture_context *tctx) -{ - struct SHA1Context sha; - int i, j, err; - uint8_t Message_Digest[20]; - bool ret = true; - char tmp[60 + 10]; - - /* - * Perform SHA-1 tests - */ - for(j = 0; j < 4; ++j) - { - ZERO_STRUCT(tmp); - torture_comment(tctx, "Test %d: %d, '%s'\n", - j+1, - repeatcount[j], - testarray[j]); - - err = SHA1Init(&sha); - torture_assert_int_equal(tctx, err, 0, "SHA1Init Error"); - - for(i = 0; i < repeatcount[j]; ++i) - { - err = SHA1Update(&sha, - (const unsigned char *) testarray[j], - strlen(testarray[j])); - torture_assert_int_equal(tctx, err, 0, "SHA1Update Error"); - } - - err = SHA1Final(Message_Digest, &sha); - torture_assert_int_equal(tctx, err, 0, - "SHA1Result Error, could not compute message digest."); - torture_comment(tctx, "\t"); - for(i = 0; i < 20 ; ++i) - { - snprintf(tmp+(i*3), sizeof(tmp) - (i*3),"%02X ", Message_Digest[i]); - torture_comment(tctx, "%02X ", Message_Digest[i]); - } - torture_comment(tctx, "\n"); - torture_comment(tctx, "Should match:\n\t%s\n", resultarray[j]); - if (strcmp(resultarray[j], tmp) != 0) { - ret = false; - } - } - - /* Test some error returns */ - err = SHA1Update(&sha,(const unsigned char *) testarray[1], 1); - torture_assert_int_equal(tctx, err, shaStateError, "SHA1Update failed"); - err = SHA1Init(0); - torture_assert_int_equal(tctx, err, shaNull, "SHA1Init failed"); - - return true; -} - - diff --git a/source4/lib/crypto/sha256.c b/source4/lib/crypto/sha256.c new file mode 100644 index 0000000000..70fe7a3099 --- /dev/null +++ b/source4/lib/crypto/sha256.c @@ -0,0 +1,234 @@ +/* + based on heildal lib/hcrypto/sha256.c. Copied to lib/crypto to avoid a link + problem. Hopefully will be removed once we solve this link problem + + (tridge) + */ + +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "includes.h" +#include "heimdal/lib/hcrypto/hash.h" +#include "sha256.h" + +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROTR(x,n) (((x)>>(n)) | ((x) << (32 - (n)))) + +#define Sigma0(x) (ROTR(x,2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define Sigma1(x) (ROTR(x,6) ^ ROTR(x,11) ^ ROTR(x,25)) +#define sigma0(x) (ROTR(x,7) ^ ROTR(x,18) ^ ((x)>>3)) +#define sigma1(x) (ROTR(x,17) ^ ROTR(x,19) ^ ((x)>>10)) + +#define A m->counter[0] +#define B m->counter[1] +#define C m->counter[2] +#define D m->counter[3] +#define E m->counter[4] +#define F m->counter[5] +#define G m->counter[6] +#define H m->counter[7] + +static const uint32_t constant_256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +void +SHA256_Init (SHA256_CTX *m) +{ + m->sz[0] = 0; + m->sz[1] = 0; + A = 0x6a09e667; + B = 0xbb67ae85; + C = 0x3c6ef372; + D = 0xa54ff53a; + E = 0x510e527f; + F = 0x9b05688c; + G = 0x1f83d9ab; + H = 0x5be0cd19; +} + +static void +calc (SHA256_CTX *m, uint32_t *in) +{ + uint32_t AA, BB, CC, DD, EE, FF, GG, HH; + uint32_t data[64]; + int i; + + AA = A; + BB = B; + CC = C; + DD = D; + EE = E; + FF = F; + GG = G; + HH = H; + + for (i = 0; i < 16; ++i) + data[i] = in[i]; + for (i = 16; i < 64; ++i) + data[i] = sigma1(data[i-2]) + data[i-7] + + sigma0(data[i-15]) + data[i - 16]; + + for (i = 0; i < 64; i++) { + uint32_t T1, T2; + + T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_256[i] + data[i]; + T2 = Sigma0(AA) + Maj(AA,BB,CC); + + HH = GG; + GG = FF; + FF = EE; + EE = DD + T1; + DD = CC; + CC = BB; + BB = AA; + AA = T1 + T2; + } + + A += AA; + B += BB; + C += CC; + D += DD; + E += EE; + F += FF; + G += GG; + H += HH; +} + +/* + * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu> + */ + +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) +static inline uint32_t +swap_uint32_t (uint32_t t) +{ + uint32_t temp1, temp2; + + temp1 = cshift(t, 16); + temp2 = temp1 >> 8; + temp1 &= 0x00ff00ff; + temp2 &= 0x00ff00ff; + temp1 <<= 8; + return temp1 | temp2; +} +#endif + +struct x32{ + unsigned int a:32; + unsigned int b:32; +}; + +void +SHA256_Update (SHA256_CTX *m, const void *v, size_t len) +{ + const unsigned char *p = v; + size_t old_sz = m->sz[0]; + size_t offset; + + m->sz[0] += len * 8; + if (m->sz[0] < old_sz) + ++m->sz[1]; + offset = (old_sz / 8) % 64; + while(len > 0){ + size_t l = min(len, 64 - offset); + memcpy(m->save + offset, p, l); + offset += l; + p += l; + len -= l; + if(offset == 64){ +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) + int i; + uint32_t current[16]; + struct x32 *u = (struct x32*)m->save; + for(i = 0; i < 8; i++){ + current[2*i+0] = swap_uint32_t(u[i].a); + current[2*i+1] = swap_uint32_t(u[i].b); + } + calc(m, current); +#else + calc(m, (uint32_t*)m->save); +#endif + offset = 0; + } + } +} + +void +SHA256_Final (void *res, SHA256_CTX *m) +{ + unsigned char zeros[72]; + unsigned offset = (m->sz[0] / 8) % 64; + unsigned int dstart = (120 - offset - 1) % 64 + 1; + + *zeros = 0x80; + memset (zeros + 1, 0, sizeof(zeros) - 1); + zeros[dstart+7] = (m->sz[0] >> 0) & 0xff; + zeros[dstart+6] = (m->sz[0] >> 8) & 0xff; + zeros[dstart+5] = (m->sz[0] >> 16) & 0xff; + zeros[dstart+4] = (m->sz[0] >> 24) & 0xff; + zeros[dstart+3] = (m->sz[1] >> 0) & 0xff; + zeros[dstart+2] = (m->sz[1] >> 8) & 0xff; + zeros[dstart+1] = (m->sz[1] >> 16) & 0xff; + zeros[dstart+0] = (m->sz[1] >> 24) & 0xff; + SHA256_Update (m, zeros, dstart + 8); + { + int i; + unsigned char *r = (unsigned char*)res; + + for (i = 0; i < 8; ++i) { + r[4*i+3] = m->counter[i] & 0xFF; + r[4*i+2] = (m->counter[i] >> 8) & 0xFF; + r[4*i+1] = (m->counter[i] >> 16) & 0xFF; + r[4*i] = (m->counter[i] >> 24) & 0xFF; + } + } +} diff --git a/source4/lib/crypto/sha256.h b/source4/lib/crypto/sha256.h new file mode 100644 index 0000000000..4a5f2cbe94 --- /dev/null +++ b/source4/lib/crypto/sha256.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: sha.h 17450 2006-05-05 11:11:43Z lha $ */ + +#ifndef HEIM_SHA_H +/* + based on heildal lib/hcrypto/sha.h. Copied to lib/crypto to avoid a link + problem. Hopefully will be removed once we solve this link problem + + (tridge) + */ +#define HEIM_SHA_H 1 + +#if 0 +/* symbol renaming */ +#define SHA1_Init hc_SHA1_Init +#define SHA1_Update hc_SHA1_Update +#define SHA1_Final hc_SHA1_Final +#define SHA256_Init hc_SHA256_Init +#define SHA256_Update hc_SHA256_Update +#define SHA256_Final hc_SHA256_Final +#endif + +/* + * SHA-1 + */ + +#define SHA_DIGEST_LENGTH 20 + +struct sha { + unsigned int sz[2]; + uint32_t counter[5]; + unsigned char save[64]; +}; + +typedef struct sha SHA_CTX; + +void SHA1_Init (struct sha *m); +void SHA1_Update (struct sha *m, const void *v, size_t len); +void SHA1_Final (void *res, struct sha *m); + +/* + * SHA-2 256 + */ + +#define SHA256_DIGEST_LENGTH 32 + +struct hc_sha256state { + unsigned int sz[2]; + uint32_t counter[8]; + unsigned char save[64]; +}; + +typedef struct hc_sha256state SHA256_CTX; + +void SHA256_Init (SHA256_CTX *); +void SHA256_Update (SHA256_CTX *, const void *, size_t); +void SHA256_Final (void *, SHA256_CTX *); + +#endif /* HEIM_SHA_H */ diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index c76222c207..aba9581ec5 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -14,7 +14,7 @@ from samba.auth import system_session from ldb import (SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, LDB_ERR_NO_SUCH_OBJECT, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS, LDB_ERR_ENTRY_ALREADY_EXISTS, LDB_ERR_UNWILLING_TO_PERFORM, - LDB_ERR_NOT_ALLOWED_ON_NON_LEAF, LDB_ERR_OTHER) + LDB_ERR_NOT_ALLOWED_ON_NON_LEAF, LDB_ERR_OTHER, LDB_ERR_INVALID_DN_SYNTAX) from samba import Ldb from subunit import SubunitTestRunner from samba import param @@ -115,6 +115,86 @@ class BasicTests(unittest.TestCase): "userAccountControl": "4096", "displayname": "ldap testy"}) + self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) + try: + ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, + "objectClass": "computer", + "cn": "LDAPtest2COMPUTER" + }) + self.fail() + except LdbError, (num, _): + self.assertEquals(num, LDB_ERR_INVALID_DN_SYNTAX) + + self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) + try: + ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, + "objectClass": "computer", + "cn": "ldaptestcomputer3", + "sAMAccountType": "805306368" + }) + self.fail() + except LdbError, (num, _): + self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM) + + self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) + try: + ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, + "objectClass": "computer", + "cn": "ldaptestcomputer3", + "userAccountControl": "0" + }) + self.fail() + except LdbError, (num, _): + self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM) + + self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn) + try: + ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn, + "objectClass": "user", + "cn": "LDAPtestuser7", + "userAccountControl": "0" + }) + self.fail() + except LdbError, (num, _): + self.assertEquals(num, LDB_ERR_UNWILLING_TO_PERFORM) + + self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn) + + ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn, + "objectClass": "user", + "cn": "LDAPtestuser7", + "userAccountControl": "2" + }) + + self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn) + + self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) + ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn, + "objectClass": "computer", + "cn": "LDAPtestCOMPUTER3" + }) + + print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))"; + res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))"); + self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res)) + + self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn)); + self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3"); + self.assertEquals(res[0]["name"][0], "ldaptestcomputer3"); + self.assertEquals(res[0]["objectClass"][0], "top"); + self.assertEquals(res[0]["objectClass"][1], "person"); + self.assertEquals(res[0]["objectClass"][2], "organizationalPerson"); + self.assertEquals(res[0]["objectClass"][3], "user"); + self.assertEquals(res[0]["objectClass"][4], "computer"); + self.assertTrue("objectGUID" in res[0]) + self.assertTrue("whenCreated" in res[0]) + self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)); + self.assertEquals(int(res[0]["primaryGroupID"][0]), 513); + self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368); + self.assertEquals(int(res[0]["userAccountControl"][0]), 546); + + self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) + print "Testing attribute or value exists behaviour" try: ldb.modify_ldif(""" @@ -125,34 +205,36 @@ servicePrincipalName: host/ldaptest2computer servicePrincipalName: host/ldaptest2computer servicePrincipalName: cifs/ldaptest2computer """) + self.fail() except LdbError, (num, msg): self.assertEquals(num, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) - ldb.modify_ldif(""" + ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ changetype: modify replace: servicePrincipalName servicePrincipalName: host/ldaptest2computer servicePrincipalName: cifs/ldaptest2computer """) - try: - ldb.modify_ldif(""" + try: + ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ changetype: modify add: servicePrincipalName servicePrincipalName: host/ldaptest2computer """) - except LdbError, (num, msg): - self.assertEquals(num, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) - - print "Testing ranged results" - ldb.modify_ldif(""" + self.fail() + except LdbError, (num, msg): + self.assertEquals(num, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) + + print "Testing ranged results" + ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ changetype: modify replace: servicePrincipalName """) - ldb.modify_ldif(""" + ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ changetype: modify add: servicePrincipalName @@ -188,53 +270,53 @@ servicePrincipalName: host/ldaptest2computer28 servicePrincipalName: host/ldaptest2computer29 """) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, - attrs=["servicePrincipalName;range=0-*"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - #print len(res[0]["servicePrincipalName;range=0-*"]) - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, + attrs=["servicePrincipalName;range=0-*"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + #print len(res[0]["servicePrincipalName;range=0-*"]) + self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") # print res[0]["servicePrincipalName;range=0-19"].length - self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20) + self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20) - # pos_11 = res[0]["servicePrincipalName;range=10-*"][18] - - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20) + # pos_11 = res[0]["servicePrincipalName;range=10-*"][18] + + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19) # print res[0]["servicePrincipalName;range=11-*"][18] # print pos_11 # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5) + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5) # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11) - res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"]) - self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") + res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"]) + self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") # print res[0]["servicePrincipalName"][18] # print pos_11 - self.assertEquals(len(res[0]["servicePrincipalName"]), 30) + self.assertEquals(len(res[0]["servicePrincipalName"]), 30) # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11) self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) @@ -322,6 +404,10 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))") self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))") + # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes) + res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))") + self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))") + print "Testing Group Modifies" ldb.modify_ldif(""" dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """ @@ -361,6 +447,26 @@ member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """ self.assertEquals(res[0]["cn"], "ldaptestUSER3") self.assertEquals(res[0]["name"], "ldaptestUSER3") + #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))" + res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))") + self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))") + + self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEquals(res[0]["cn"], "ldaptestUSER3") + self.assertEquals(res[0]["name"], "ldaptestUSER3") + + #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))" + res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))") + self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))") + + self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) + self.assertEquals(res[0]["cn"], "ldaptestUSER3") + self.assertEquals(res[0]["name"], "ldaptestUSER3") + + #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))" + res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") + self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") + # This is a Samba special, and does not exist in real AD # print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")" # res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") @@ -534,7 +640,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertTrue("whenCreated" in res[0]) self.assertEquals(res[0]["objectCategory"], ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn)) self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368) - # self.assertEquals(res[0].userAccountControl, 546) + self.assertEquals(int(res[0]["userAccountControl"][0]), 546) self.assertEquals(res[0]["memberOf"][0], ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) self.assertEquals(len(res[0]["memberOf"]), 1) @@ -578,8 +684,8 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertTrue("whenCreated" in res[0]) self.assertEquals(res[0]["objectCategory"], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)) self.assertEquals(int(res[0]["primaryGroupID"][0]), 513) - # self.assertEquals(res[0].sAMAccountType, 805306368) - # self.assertEquals(res[0].userAccountControl, 546) + self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368) + self.assertEquals(int(res[0]["userAccountControl"][0]), 546) self.assertEquals(res[0]["memberOf"][0], "CN=ldaptestgroup2,CN=Users," + self.base_dn) self.assertEquals(len(res[0]["memberOf"]), 1) @@ -641,7 +747,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertTrue("whenCreated" in res[0]) self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn) self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306369) - # self.assertEquals(res[0].userAccountControl, 4098) + self.assertEquals(int(res[0]["userAccountControl"][0]), 4096) ldb.delete(res[0].dn) diff --git a/source4/lib/torture/torture.h b/source4/lib/torture/torture.h index 15b04c2397..f023f319ff 100644 --- a/source4/lib/torture/torture.h +++ b/source4/lib/torture/torture.h @@ -257,7 +257,7 @@ void torture_result(struct torture_context *test, do { const void *__got = (got), *__expected = (expected); \ if (memcmp(__got, __expected, len) != 0) { \ torture_result(torture_ctx, TORTURE_FAIL, \ - __location__": "#got" of len %d did not match"#expected": %s", len, cmt); \ + __location__": "#got" of len %d did not match"#expected": %s", (int)len, cmt); \ return false; \ } \ } while(0) diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index 19d51893a6..8e23510f06 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -906,15 +906,24 @@ enum smb_setfileinfo_level { RAW_SFILEINFO_RENAME_INFORMATION = SMB_SFILEINFO_RENAME_INFORMATION, RAW_SFILEINFO_DISPOSITION_INFORMATION = SMB_SFILEINFO_DISPOSITION_INFORMATION, RAW_SFILEINFO_POSITION_INFORMATION = SMB_SFILEINFO_POSITION_INFORMATION, + RAW_SFILEINFO_FULL_EA_INFORMATION = SMB_SFILEINFO_FULL_EA_INFORMATION, RAW_SFILEINFO_MODE_INFORMATION = SMB_SFILEINFO_MODE_INFORMATION, RAW_SFILEINFO_ALLOCATION_INFORMATION = SMB_SFILEINFO_ALLOCATION_INFORMATION, RAW_SFILEINFO_END_OF_FILE_INFORMATION = SMB_SFILEINFO_END_OF_FILE_INFORMATION, - RAW_SFILEINFO_1023 = SMB_SFILEINFO_1023, + RAW_SFILEINFO_PIPE_INFORMATION = SMB_SFILEINFO_PIPE_INFORMATION, + RAW_SFILEINFO_VALID_DATA_INFORMATION = SMB_SFILEINFO_VALID_DATA_INFORMATION, + RAW_SFILEINFO_SHORT_NAME_INFORMATION = SMB_SFILEINFO_SHORT_NAME_INFORMATION, RAW_SFILEINFO_1025 = SMB_SFILEINFO_1025, + RAW_SFILEINFO_1027 = SMB_SFILEINFO_1027, RAW_SFILEINFO_1029 = SMB_SFILEINFO_1029, + RAW_SFILEINFO_1030 = SMB_SFILEINFO_1030, + RAW_SFILEINFO_1031 = SMB_SFILEINFO_1031, RAW_SFILEINFO_1032 = SMB_SFILEINFO_1032, - RAW_SFILEINFO_1039 = SMB_SFILEINFO_1039, - RAW_SFILEINFO_1040 = SMB_SFILEINFO_1040, + RAW_SFILEINFO_1036 = SMB_SFILEINFO_1036, + RAW_SFILEINFO_1041 = SMB_SFILEINFO_1041, + RAW_SFILEINFO_1042 = SMB_SFILEINFO_1042, + RAW_SFILEINFO_1043 = SMB_SFILEINFO_1043, + RAW_SFILEINFO_1044 = SMB_SFILEINFO_1044, /* cope with breakage in SMB2 */ RAW_SFILEINFO_RENAME_INFORMATION_SMB2 = SMB_SFILEINFO_RENAME_INFORMATION|0x80000000, @@ -1901,7 +1910,7 @@ union smb_lock { uint16_t ulock_cnt; uint16_t lock_cnt; struct smb_lock_entry { - uint16_t pid; + uint32_t pid; /* 16 bits in SMB1 */ uint64_t offset; uint64_t count; } *locks; /* unlocks are first in the arrray */ diff --git a/source4/libcli/raw/rawsetfileinfo.c b/source4/libcli/raw/rawsetfileinfo.c index 16052e8708..5a4706778a 100644 --- a/source4/libcli/raw/rawsetfileinfo.c +++ b/source4/libcli/raw/rawsetfileinfo.c @@ -110,12 +110,20 @@ bool smb_raw_setfileinfo_passthru(TALLOC_CTX *mem_ctx, } /* Unhandled levels */ - case RAW_SFILEINFO_1023: + case RAW_SFILEINFO_PIPE_INFORMATION: + case RAW_SFILEINFO_VALID_DATA_INFORMATION: + case RAW_SFILEINFO_SHORT_NAME_INFORMATION: case RAW_SFILEINFO_1025: + case RAW_SFILEINFO_1027: case RAW_SFILEINFO_1029: + case RAW_SFILEINFO_1030: + case RAW_SFILEINFO_1031: case RAW_SFILEINFO_1032: - case RAW_SFILEINFO_1039: - case RAW_SFILEINFO_1040: + case RAW_SFILEINFO_1036: + case RAW_SFILEINFO_1041: + case RAW_SFILEINFO_1042: + case RAW_SFILEINFO_1043: + case RAW_SFILEINFO_1044: break; default: @@ -227,12 +235,21 @@ static bool smb_raw_setinfo_backend(struct smbcli_tree *tree, parms, blob); /* Unhandled passthru levels */ - case RAW_SFILEINFO_1023: + case RAW_SFILEINFO_PIPE_INFORMATION: + case RAW_SFILEINFO_VALID_DATA_INFORMATION: + case RAW_SFILEINFO_SHORT_NAME_INFORMATION: + case RAW_SFILEINFO_FULL_EA_INFORMATION: case RAW_SFILEINFO_1025: + case RAW_SFILEINFO_1027: case RAW_SFILEINFO_1029: + case RAW_SFILEINFO_1030: + case RAW_SFILEINFO_1031: case RAW_SFILEINFO_1032: - case RAW_SFILEINFO_1039: - case RAW_SFILEINFO_1040: + case RAW_SFILEINFO_1036: + case RAW_SFILEINFO_1041: + case RAW_SFILEINFO_1042: + case RAW_SFILEINFO_1043: + case RAW_SFILEINFO_1044: return smb_raw_setfileinfo_passthru(mem_ctx, parms->generic.level, parms, blob); diff --git a/source4/libcli/raw/trans2.h b/source4/libcli/raw/trans2.h index 5b7987aa8c..63632eb5ed 100644 --- a/source4/libcli/raw/trans2.h +++ b/source4/libcli/raw/trans2.h @@ -217,32 +217,37 @@ Found 13 valid levels #define SMB_SFILEINFO_UNIX_INFO2 0x20b #define SMB_SFILEINFO_BASIC_INFORMATION 1004 #define SMB_SFILEINFO_RENAME_INFORMATION 1010 +#define SMB_SFILEINFO_LINK_INFORMATION 1011 #define SMB_SFILEINFO_DISPOSITION_INFORMATION 1013 #define SMB_SFILEINFO_POSITION_INFORMATION 1014 +#define SMB_SFILEINFO_FULL_EA_INFORMATION 1015 #define SMB_SFILEINFO_MODE_INFORMATION 1016 #define SMB_SFILEINFO_ALLOCATION_INFORMATION 1019 #define SMB_SFILEINFO_END_OF_FILE_INFORMATION 1020 - -/* filemon shows FilePipeInformation */ -#define SMB_SFILEINFO_1023 1023 +#define SMB_SFILEINFO_PIPE_INFORMATION 1023 +#define SMB_SFILEINFO_VALID_DATA_INFORMATION 1039 +#define SMB_SFILEINFO_SHORT_NAME_INFORMATION 1040 /* filemon shows FilePipeRemoteInformation */ #define SMB_SFILEINFO_1025 1025 +/* vista scan responds */ +#define SMB_SFILEINFO_1027 1027 + /* filemon shows CopyOnWriteInformation */ #define SMB_SFILEINFO_1029 1029 /* filemon shows OleClassIdInformation */ #define SMB_SFILEINFO_1032 1032 -/* seems to be the file size - perhaps valid data size? - filemon shows 'InheritContentIndexInfo' -*/ -#define SMB_SFILEINFO_1039 1039 - -/* OLE_INFORMATION? */ -#define SMB_SFILEINFO_1040 1040 - +/* vista scan responds to these */ +#define SMB_SFILEINFO_1030 1030 +#define SMB_SFILEINFO_1031 1031 +#define SMB_SFILEINFO_1036 1036 +#define SMB_SFILEINFO_1041 1041 +#define SMB_SFILEINFO_1042 1042 +#define SMB_SFILEINFO_1043 1043 +#define SMB_SFILEINFO_1044 1044 /* trans2 findfirst levels */ /* diff --git a/source4/libcli/smb2/signing.c b/source4/libcli/smb2/signing.c index 01f7576134..16c0ff99c1 100644 --- a/source4/libcli/smb2/signing.c +++ b/source4/libcli/smb2/signing.c @@ -23,7 +23,7 @@ #include "libcli/raw/libcliraw.h" #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" -#include "heimdal/lib/hcrypto/sha.h" +#include "lib/crypto/crypto.h" /* NOTE: this code does not yet interoperate with the windows SMB2 @@ -54,7 +54,7 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) { struct smb2_request_buffer *buf = &req->out; uint64_t session_id; - SHA256_CTX m; + struct HMACSHA256Context m; uint8_t res[32]; if (!req->transport->signing.doing_signing || @@ -85,11 +85,9 @@ NTSTATUS smb2_sign_message(struct smb2_request *req) SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); ZERO_STRUCT(m); - SHA256_Init(&m); - SHA256_Update(&m, req->transport->signing.session_key.data, - req->transport->signing.session_key.length); - SHA256_Update(&m, buf->buffer+NBT_HDR_SIZE, buf->size-NBT_HDR_SIZE); - SHA256_Final(res, &m); + hmac_sha256_init(req->transport->signing.session_key.data, 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)); @@ -110,7 +108,7 @@ NTSTATUS smb2_check_signature(struct smb2_transport *transport, uint8_t *buffer, uint_t length) { uint64_t session_id; - SHA256_CTX m; + struct HMACSHA256Context m; uint8_t res[SHA256_DIGEST_LENGTH]; uint8_t sig[16]; @@ -147,10 +145,9 @@ NTSTATUS smb2_check_signature(struct smb2_transport *transport, memset(buffer + NBT_HDR_SIZE + SMB2_HDR_SIGNATURE, 0, 16); ZERO_STRUCT(m); - SHA256_Init(&m); - SHA256_Update(&m, transport->signing.session_key.data, 16); - SHA256_Update(&m, buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE); - SHA256_Final(res, &m); + hmac_sha256_init(transport->signing.session_key.data, 16, &m); + hmac_sha256_update(buffer+NBT_HDR_SIZE, length-NBT_HDR_SIZE, &m); + hmac_sha256_final(res, &m); memcpy(buffer+NBT_HDR_SIZE+SMB2_HDR_SIGNATURE, sig, 16); diff --git a/source4/librpc/idl/opendb.idl b/source4/librpc/idl/opendb.idl index 72bf23a9b4..cdbaa6cb1b 100644 --- a/source4/librpc/idl/opendb.idl +++ b/source4/librpc/idl/opendb.idl @@ -35,6 +35,8 @@ interface opendb typedef [public] struct { boolean8 delete_on_close; + NTTIME open_write_time; + NTTIME changed_write_time; utf8string path; uint32 num_entries; opendb_entry entries[num_entries]; diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c index c87eca8aff..3b34873152 100644 --- a/source4/ntvfs/common/brlock.c +++ b/source4/ntvfs/common/brlock.c @@ -109,7 +109,7 @@ NTSTATUS brl_remove_pending(struct brl_context *brl, */ NTSTATUS brl_locktest(struct brl_context *brl, struct brl_handle *brlh, - uint16_t smbpid, + uint32_t smbpid, uint64_t start, uint64_t size, enum brl_type lock_type) { diff --git a/source4/ntvfs/common/brlock_tdb.c b/source4/ntvfs/common/brlock_tdb.c index 362a6d01e2..c94b9b446e 100644 --- a/source4/ntvfs/common/brlock_tdb.c +++ b/source4/ntvfs/common/brlock_tdb.c @@ -57,7 +57,7 @@ struct brl_context { */ struct lock_context { struct server_id server; - uint16_t smbpid; + uint32_t smbpid; struct brl_context *ctx; }; @@ -286,7 +286,7 @@ static NTSTATUS brl_tdb_lock_failed(struct brl_handle *brlh, struct lock_struct */ static NTSTATUS brl_tdb_lock(struct brl_context *brl, struct brl_handle *brlh, - uint16_t smbpid, + uint32_t smbpid, uint64_t start, uint64_t size, enum brl_type lock_type, void *notify_ptr) @@ -436,7 +436,7 @@ static void brl_tdb_notify_all(struct brl_context *brl, */ static NTSTATUS brl_tdb_unlock(struct brl_context *brl, struct brl_handle *brlh, - uint16_t smbpid, + uint32_t smbpid, uint64_t start, uint64_t size) { TDB_DATA kbuf, dbuf; @@ -581,7 +581,7 @@ static NTSTATUS brl_tdb_remove_pending(struct brl_context *brl, */ static NTSTATUS brl_tdb_locktest(struct brl_context *brl, struct brl_handle *brlh, - uint16_t smbpid, + uint32_t smbpid, uint64_t start, uint64_t size, enum brl_type lock_type) { diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 2913ea8431..6917bad52a 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -97,11 +97,13 @@ DATA_BLOB odb_get_key(TALLOC_CTX *mem_ctx, struct odb_lock *lck) */ NTSTATUS odb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - int *fd, bool allow_level_II_oplock, + int *fd, NTTIME open_write_time, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { return ops->odb_open_file(lck, file_handle, path, - fd, allow_level_II_oplock, + fd, open_write_time, + allow_level_II_oplock, oplock_level, oplock_granted); } @@ -159,15 +161,23 @@ NTSTATUS odb_set_delete_on_close(struct odb_lock *lck, bool del_on_close) } /* - return the current value of the delete_on_close bit, and how many - people still have the file open + update the write time on an open file */ -NTSTATUS odb_get_delete_on_close(struct odb_context *odb, - DATA_BLOB *key, bool *del_on_close) +NTSTATUS odb_set_write_time(struct odb_lock *lck, + NTTIME write_time, bool force) { - return ops->odb_get_delete_on_close(odb, key, del_on_close); + return ops->odb_set_write_time(lck, write_time, force); } +/* + return the current value of the delete_on_close bit, + and the current write time. +*/ +NTSTATUS odb_get_file_infos(struct odb_context *odb, DATA_BLOB *key, + bool *del_on_close, NTTIME *write_time) +{ + return ops->odb_get_file_infos(odb, key, del_on_close, write_time); +} /* determine if a file can be opened with the given share_access, diff --git a/source4/ntvfs/common/opendb.h b/source4/ntvfs/common/opendb.h index 045476337a..179db111ca 100644 --- a/source4/ntvfs/common/opendb.h +++ b/source4/ntvfs/common/opendb.h @@ -27,7 +27,8 @@ struct opendb_ops { DATA_BLOB (*odb_get_key)(TALLOC_CTX *mem_ctx, struct odb_lock *lck); NTSTATUS (*odb_open_file)(struct odb_lock *lck, void *file_handle, const char *path, - int *fd, bool allow_level_II_oplock, + int *fd, NTTIME open_write_time, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted); NTSTATUS (*odb_open_file_pending)(struct odb_lock *lck, void *private); NTSTATUS (*odb_close_file)(struct odb_lock *lck, void *file_handle, @@ -36,8 +37,10 @@ struct opendb_ops { NTSTATUS (*odb_rename)(struct odb_lock *lck, const char *path); NTSTATUS (*odb_get_path)(struct odb_lock *lck, const char **path); NTSTATUS (*odb_set_delete_on_close)(struct odb_lock *lck, bool del_on_close); - NTSTATUS (*odb_get_delete_on_close)(struct odb_context *odb, - DATA_BLOB *key, bool *del_on_close); + NTSTATUS (*odb_set_write_time)(struct odb_lock *lck, + NTTIME write_time, bool force); + NTSTATUS (*odb_get_file_infos)(struct odb_context *odb, DATA_BLOB *key, + bool *del_on_close, NTTIME *write_time); NTSTATUS (*odb_can_open)(struct odb_lock *lck, uint32_t stream_id, uint32_t share_access, uint32_t access_mask, bool delete_on_close, diff --git a/source4/ntvfs/common/opendb_tdb.c b/source4/ntvfs/common/opendb_tdb.c index 99c0a95c20..d7531297ed 100644 --- a/source4/ntvfs/common/opendb_tdb.c +++ b/source4/ntvfs/common/opendb_tdb.c @@ -452,7 +452,8 @@ static NTSTATUS odb_tdb_open_can_internal(struct odb_context *odb, */ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, void *file_handle, const char *path, - int *fd, bool allow_level_II_oplock, + int *fd, NTTIME open_write_time, + bool allow_level_II_oplock, uint32_t oplock_level, uint32_t *oplock_granted) { struct odb_context *odb = lck->odb; @@ -474,6 +475,10 @@ static NTSTATUS odb_tdb_open_file(struct odb_lock *lck, NT_STATUS_HAVE_NO_MEMORY(lck->file.path); } + if (lck->file.open_write_time == 0) { + lck->file.open_write_time = open_write_time; + } + /* possibly grant an exclusive, batch or level2 oplock */ @@ -785,20 +790,53 @@ static NTSTATUS odb_tdb_set_delete_on_close(struct odb_lock *lck, bool del_on_cl } /* + update the write time on an open file +*/ +static NTSTATUS odb_tdb_set_write_time(struct odb_lock *lck, + NTTIME write_time, bool force) +{ + if (lck->file.path == NULL) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (lck->file.changed_write_time != 0 && !force) { + return NT_STATUS_OK; + } + + lck->file.changed_write_time = write_time; + + return odb_push_record(lck, &lck->file); +} + +/* return the current value of the delete_on_close bit, and how many people still have the file open */ -static NTSTATUS odb_tdb_get_delete_on_close(struct odb_context *odb, - DATA_BLOB *key, bool *del_on_close) +static NTSTATUS odb_tdb_get_file_infos(struct odb_context *odb, DATA_BLOB *key, + bool *del_on_close, NTTIME *write_time) { struct odb_lock *lck; - (*del_on_close) = false; + if (del_on_close) { + *del_on_close = false; + } + if (write_time) { + *write_time = 0; + } lck = odb_lock(odb, odb, key); NT_STATUS_HAVE_NO_MEMORY(lck); - (*del_on_close) = lck->file.delete_on_close; + if (del_on_close) { + *del_on_close = lck->file.delete_on_close; + } + if (write_time) { + if (lck->file.changed_write_time == 0) { + *write_time = lck->file.open_write_time; + } else { + *write_time = lck->file.changed_write_time; + } + } talloc_free(lck); @@ -852,7 +890,8 @@ static const struct opendb_ops opendb_tdb_ops = { .odb_rename = odb_tdb_rename, .odb_get_path = odb_tdb_get_path, .odb_set_delete_on_close = odb_tdb_set_delete_on_close, - .odb_get_delete_on_close = odb_tdb_get_delete_on_close, + .odb_set_write_time = odb_tdb_set_write_time, + .odb_get_file_infos = odb_tdb_get_file_infos, .odb_can_open = odb_tdb_can_open, .odb_update_oplock = odb_tdb_update_oplock, .odb_break_oplocks = odb_tdb_break_oplocks diff --git a/source4/ntvfs/ntvfs.h b/source4/ntvfs/ntvfs.h index 7a2edc7e2c..5de8a8b649 100644 --- a/source4/ntvfs/ntvfs.h +++ b/source4/ntvfs/ntvfs.h @@ -263,7 +263,7 @@ struct ntvfs_request { struct auth_session_info *session_info; /* the smb pid is needed for locking contexts */ - uint16_t smbpid; + uint32_t smbpid; /* * client capabilities diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index d705758475..4f3a7e2198 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -986,8 +986,8 @@ NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs, NTVFS lock generic to any mapper */ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, - union smb_lock *lck) + struct ntvfs_request *req, + union smb_lock *lck) { union smb_lock *lck2; struct smb_lock_entry *locks; @@ -1035,7 +1035,8 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, case RAW_LOCK_SMB2: { /* this is only approximate! We need to change the generic structure to fix this properly */ - int i, j; + int i; + bool isunlock; if (lck->smb2.in.lock_count < 1) { return NT_STATUS_INVALID_PARAMETER; } @@ -1051,32 +1052,28 @@ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, if (lck2->generic.in.locks == NULL) { return NT_STATUS_NO_MEMORY; } + /* only the first lock gives the UNLOCK bit - see + MS-SMB2 3.3.5.14 */ + if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_UNLOCK) { + lck2->generic.in.ulock_cnt = lck->smb2.in.lock_count; + isunlock = true; + } else { + lck2->generic.in.lock_cnt = lck->smb2.in.lock_count; + isunlock = false; + } for (i=0;i<lck->smb2.in.lock_count;i++) { - if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) { - break; - } - j = lck2->generic.in.ulock_cnt; - if (lck->smb2.in.locks[i].flags & - (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE)) { + if (isunlock && + (lck->smb2.in.locks[i].flags & + (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE))) { return NT_STATUS_INVALID_PARAMETER; } - lck2->generic.in.ulock_cnt++; - lck2->generic.in.locks[j].pid = 0; - lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; - lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; - lck2->generic.in.locks[j].pid = 0; - } - for (;i<lck->smb2.in.lock_count;i++) { - if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK) { - /* w2008 requires unlocks to come first */ + if (!isunlock && + (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) { return NT_STATUS_INVALID_PARAMETER; } - j = lck2->generic.in.ulock_cnt + lck2->generic.in.lock_cnt; - lck2->generic.in.lock_cnt++; - lck2->generic.in.locks[j].pid = 0; - lck2->generic.in.locks[j].offset = lck->smb2.in.locks[i].offset; - lck2->generic.in.locks[j].count = lck->smb2.in.locks[i].length; - lck2->generic.in.locks[j].pid = 0; + lck2->generic.in.locks[i].pid = req->smbpid; + lck2->generic.in.locks[i].offset = lck->smb2.in.locks[i].offset; + lck2->generic.in.locks[i].count = lck->smb2.in.locks[i].length; if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) { lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK; } diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c index 04f6ad78d0..a14c8f64ae 100644 --- a/source4/ntvfs/posix/pvfs_fileinfo.c +++ b/source4/ntvfs/posix/pvfs_fileinfo.c @@ -52,8 +52,13 @@ static uint32_t dos_mode_from_stat(struct pvfs_state *pvfs, struct stat *st) /* fill in the dos file attributes for a file */ -NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd) +NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, + uint_t flags, int fd) { + NTSTATUS status; + DATA_BLOB lkey; + NTTIME write_time; + /* make directories appear as size 0 with 1 link */ if (S_ISDIR(name->st.st_mode)) { name->st.st_size = 0; @@ -85,7 +90,29 @@ NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name, name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino; name->dos.flags = 0; - return pvfs_dosattrib_load(pvfs, name, fd); + status = pvfs_dosattrib_load(pvfs, name, fd); + NT_STATUS_NOT_OK_RETURN(status); + + if (flags & PVFS_RESOLVE_NO_OPENDB) { + return NT_STATUS_OK; + } + + status = pvfs_locking_key(name, name, &lkey); + NT_STATUS_NOT_OK_RETURN(status); + + status = odb_get_file_infos(pvfs->odb_context, &lkey, + NULL, &write_time); + data_blob_free(&lkey); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("WARNING: odb_get_file_infos: %s\n", nt_errstr(status))); + return status; + } + + if (!null_time(write_time)) { + name->dos.write_time = write_time; + } + + return NT_STATUS_OK; } diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index 822b28246a..0054455838 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -31,7 +31,7 @@ */ NTSTATUS pvfs_check_lock(struct pvfs_state *pvfs, struct pvfs_file *f, - uint16_t smbpid, + uint32_t smbpid, uint64_t offset, uint64_t count, enum brl_type rw) { diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index dada9f503f..43203086f8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -280,6 +280,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->oplock = NULL; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && @@ -317,7 +318,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - NULL, false, OPLOCK_NONE, NULL); + NULL, name->dos.write_time, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -377,7 +379,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } status = odb_open_file(lck, f->handle, name->full_name, - NULL, false, OPLOCK_NONE, NULL); + NULL, name->dos.write_time, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -433,6 +436,9 @@ cleanup_delete: */ static int pvfs_handle_destructor(struct pvfs_file_handle *h) { + talloc_free(h->write_time.update_event); + h->write_time.update_event = NULL; + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -451,6 +457,14 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) h->fd = -1; } + if (!h->write_time.update_forced && + h->write_time.update_on_close && + h->write_time.close_time == 0) { + struct timeval tv; + tv = timeval_current(); + h->write_time.close_time = timeval_to_nttime(&tv); + } + if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; @@ -462,6 +476,26 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) return 0; } + if (h->write_time.update_forced) { + status = odb_get_file_infos(h->pvfs->odb_context, + &h->odb_locking_key, + NULL, + &h->write_time.close_time); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable get write time for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } + + h->write_time.update_forced = false; + h->write_time.update_on_close = true; + } else if (h->write_time.update_on_close) { + status = odb_set_write_time(lck, h->write_time.close_time, true); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable set write time for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } + } + status = odb_close_file(lck, h, &delete_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", @@ -484,11 +518,26 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) FILE_NOTIFY_CHANGE_FILE_NAME, delete_path); } + h->write_time.update_on_close = false; } talloc_free(lck); } + if (h->write_time.update_on_close) { + struct timeval tv[2]; + + nttime_to_timeval(&tv[0], h->name->dos.access_time); + nttime_to_timeval(&tv[1], h->write_time.close_time); + + if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) { + if (utimes(h->name->full_name, tv) == -1) { + DEBUG(0,("pvfs_handle_destructor: utimes() failed '%s' - %s\n", + h->name->full_name, strerror(errno))); + } + } + } + return 0; } @@ -594,8 +643,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, DATA_BLOB locking_key; status = pvfs_locking_key(parent, req, &locking_key); NT_STATUS_NOT_OK_RETURN(status); - status = odb_get_delete_on_close(pvfs->odb_context, &locking_key, - &del_on_close); + status = odb_get_file_infos(pvfs->odb_context, &locking_key, + &del_on_close, NULL); NT_STATUS_NOT_OK_RETURN(status); if (del_on_close) { return NT_STATUS_DELETE_PENDING; @@ -638,7 +687,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(pvfs, fd, name); + status = pvfs_resolve_name_fd(pvfs, fd, name, 0); if (!NT_STATUS_IS_OK(status)) { close(fd); return status; @@ -730,10 +779,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = true; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; status = odb_open_file(lck, f->handle, name->full_name, - &f->handle->fd, allow_level_II_oplock, + &f->handle->fd, name->dos.write_time, + allow_level_II_oplock, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { @@ -1334,6 +1385,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = false; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; /* form the lock context used for byte range locking and @@ -1437,7 +1489,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - &f->handle->fd, allow_level_II_oplock, + &f->handle->fd, name->dos.write_time, + allow_level_II_oplock, oplock_level, &oplock_granted); if (!NT_STATUS_IS_OK(status)) { @@ -1476,7 +1529,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name); + status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name, PVFS_RESOLVE_NO_OPENDB); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; @@ -1538,7 +1591,6 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; - struct utimbuf unix_times; if (io->generic.level == RAW_CLOSE_SPLCLOSE) { return NT_STATUS_DOS(ERRSRV, ERRerror); @@ -1554,9 +1606,9 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, } if (!null_time(io->generic.in.write_time)) { - unix_times.actime = 0; - unix_times.modtime = io->close.in.write_time; - utime(f->handle->name->full_name, &unix_times); + f->handle->write_time.update_forced = false; + f->handle->write_time.update_on_close = true; + unix_to_nt_time(&f->handle->write_time.close_time, io->generic.in.write_time); } if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { @@ -1915,8 +1967,8 @@ bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle * NTSTATUS status; bool del_on_close; - status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, - &del_on_close); + status = odb_get_file_infos(pvfs->odb_context, &h->odb_locking_key, + &del_on_close, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); return false; diff --git a/source4/ntvfs/posix/pvfs_oplock.c b/source4/ntvfs/posix/pvfs_oplock.c index dfa3697af7..71add72987 100644 --- a/source4/ntvfs/posix/pvfs_oplock.c +++ b/source4/ntvfs/posix/pvfs_oplock.c @@ -177,7 +177,7 @@ static void pvfs_oplock_break_dispatch(struct messaging_context *msg, opb = *p; } else { DEBUG(0,("%s: ignore oplock break with length[%u]\n", - __location__, data->length)); + __location__, (unsigned)data->length)); return; } if (opb.file_handle != opl->handle) { diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index 5c2a627084..d8ea5896e5 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -287,7 +287,9 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, /* get a pvfs_filename source object */ status = pvfs_resolve_partial(pvfs, mem_ctx, - dir_path, fname1, &name1); + dir_path, fname1, + PVFS_RESOLVE_NO_OPENDB, + &name1); if (!NT_STATUS_IS_OK(status)) { goto failed; } @@ -306,7 +308,9 @@ static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs, /* get a pvfs_filename dest object */ status = pvfs_resolve_partial(pvfs, mem_ctx, - dir_path, fname2, &name2); + dir_path, fname2, + PVFS_RESOLVE_NO_OPENDB, + &name2); if (NT_STATUS_IS_OK(status)) { status = pvfs_can_delete(pvfs, req, name2, NULL); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 2e97925c49..0f19788b97 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -57,7 +57,9 @@ static int component_compare(struct pvfs_state *pvfs, const char *comp, const ch TODO: add a cache for previously resolved case-insensitive names TODO: add mangled name support */ -static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename *name) +static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, + struct pvfs_filename *name, + uint_t flags) { /* break into a series of components */ int num_components; @@ -175,7 +177,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * name->full_name = partial_name; if (name->exists) { - return pvfs_fill_dos_info(pvfs, name, -1); + return pvfs_fill_dos_info(pvfs, name, flags, -1); } return NT_STATUS_OK; @@ -515,7 +517,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* we need to search for a matching name */ saved_name = (*name)->full_name; (*name)->full_name = dir_name; - status = pvfs_case_search(pvfs, *name); + status = pvfs_case_search(pvfs, *name, flags); if (!NT_STATUS_IS_OK(status)) { /* the directory doesn't exist */ (*name)->full_name = saved_name; @@ -536,11 +538,11 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* if we can stat() the full name now then we are done */ if (stat((*name)->full_name, &(*name)->st) == 0) { (*name)->exists = true; - return pvfs_fill_dos_info(pvfs, *name, -1); + return pvfs_fill_dos_info(pvfs, *name, flags, -1); } /* search for a matching filename */ - status = pvfs_case_search(pvfs, *name); + status = pvfs_case_search(pvfs, *name, flags); return status; } @@ -556,7 +558,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, */ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, const char *unix_dir, const char *fname, - struct pvfs_filename **name) + uint_t flags, struct pvfs_filename **name) { NTSTATUS status; @@ -581,7 +583,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->stream_name = NULL; (*name)->stream_id = 0; - status = pvfs_fill_dos_info(pvfs, *name, -1); + status = pvfs_fill_dos_info(pvfs, *name, flags, -1); return status; } @@ -593,7 +595,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, to update the pvfs_filename stat information, and by pvfs_open() */ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, - struct pvfs_filename *name) + struct pvfs_filename *name, uint_t flags) { dev_t device = (dev_t)0; ino_t inode = 0; @@ -626,7 +628,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, name->exists = true; - return pvfs_fill_dos_info(pvfs, name, fd); + return pvfs_fill_dos_info(pvfs, name, flags, fd); } /* @@ -703,9 +705,17 @@ NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs, talloc_free(lck); } - status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); + /* + * TODO: pass PVFS_RESOLVE_NO_OPENDB and get + * the write time from odb_lock() above. + */ + status = pvfs_resolve_name_fd(pvfs, h->fd, h->name, 0); NT_STATUS_NOT_OK_RETURN(status); + if (!null_nttime(h->write_time.close_time)) { + h->name->dos.write_time = h->write_time.close_time; + } + return NT_STATUS_OK; } @@ -755,7 +765,7 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->stream_name = NULL; (*name)->stream_id = 0; - status = pvfs_fill_dos_info(pvfs, *name, -1); + status = pvfs_fill_dos_info(pvfs, *name, PVFS_RESOLVE_NO_OPENDB, -1); return status; } diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c index e47406dc09..e0fe4fb64d 100644 --- a/source4/ntvfs/posix/pvfs_search.c +++ b/source4/ntvfs/posix/pvfs_search.c @@ -84,7 +84,7 @@ static NTSTATUS fill_search_info(struct pvfs_state *pvfs, in pvfs_list_seek_ofs() for how we cope with this */ - status = pvfs_resolve_partial(pvfs, file, unix_path, fname, &name); + status = pvfs_resolve_partial(pvfs, file, unix_path, fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_seek.c b/source4/ntvfs/posix/pvfs_seek.c index 3ea8b7cb6e..a3c4024ed7 100644 --- a/source4/ntvfs/posix/pvfs_seek.c +++ b/source4/ntvfs/posix/pvfs_seek.c @@ -52,7 +52,7 @@ NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs, break; case SEEK_MODE_END: - status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); + status = pvfs_resolve_name_fd(pvfs, h->fd, h->name, PVFS_RESOLVE_NO_OPENDB); h->seek_offset = h->name->st.st_size + io->lseek.in.offset; break; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index 1dd2c075d9..2cde5f42aa 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -273,7 +273,6 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, union smb_setfileinfo *info) { struct pvfs_state *pvfs = ntvfs->private_data; - struct utimbuf unix_times; struct pvfs_file *f; struct pvfs_file_handle *h; struct pvfs_filename newstats; @@ -437,23 +436,54 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, } /* possibly change the file timestamps */ - ZERO_STRUCT(unix_times); if (newstats.dos.create_time != h->name->dos.create_time) { change_mask |= FILE_NOTIFY_CHANGE_CREATION; } if (newstats.dos.access_time != h->name->dos.access_time) { - unix_times.actime = nt_time_to_unix(newstats.dos.access_time); change_mask |= FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (newstats.dos.write_time != h->name->dos.write_time) { - unix_times.modtime = nt_time_to_unix(newstats.dos.write_time); change_mask |= FILE_NOTIFY_CHANGE_LAST_WRITE; } - if (unix_times.actime != 0 || unix_times.modtime != 0) { - if (utime(h->name->full_name, &unix_times) == -1) { - return pvfs_map_errno(pvfs, errno); + if ((change_mask & FILE_NOTIFY_CHANGE_LAST_ACCESS) || + (change_mask & FILE_NOTIFY_CHANGE_LAST_WRITE)) { + struct timeval tv[2]; + + nttime_to_timeval(&tv[0], newstats.dos.access_time); + nttime_to_timeval(&tv[1], newstats.dos.write_time); + + if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) { + if (utimes(h->name->full_name, tv) == -1) { + DEBUG(0,("pvfs_setfileinfo: utimes() failed '%s' - %s\n", + h->name->full_name, strerror(errno))); + return pvfs_map_errno(pvfs, errno); + } } } + if (change_mask & FILE_NOTIFY_CHANGE_LAST_WRITE) { + struct odb_lock *lck; + + lck = odb_lock(req, h->pvfs->odb_context, &h->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for write time update\n")); + return NT_STATUS_INTERNAL_ERROR; + } + + status = odb_set_write_time(lck, newstats.dos.write_time, true); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update write time: %s\n", + nt_errstr(status))); + talloc_free(lck); + return status; + } + + talloc_free(lck); + + h->write_time.update_forced = true; + h->write_time.update_on_close = false; + talloc_free(h->write_time.update_event); + h->write_time.update_event = NULL; + } /* possibly change the attribute */ if (newstats.dos.attrib != h->name->dos.attrib) { @@ -570,7 +600,6 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; struct pvfs_filename newstats; NTSTATUS status; - struct utimbuf unix_times; uint32_t access_needed; uint32_t change_mask = 0; struct odb_lock *lck = NULL; @@ -736,21 +765,51 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, } /* possibly change the file timestamps */ - ZERO_STRUCT(unix_times); if (newstats.dos.create_time != name->dos.create_time) { change_mask |= FILE_NOTIFY_CHANGE_CREATION; } if (newstats.dos.access_time != name->dos.access_time) { - unix_times.actime = nt_time_to_unix(newstats.dos.access_time); change_mask |= FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (newstats.dos.write_time != name->dos.write_time) { - unix_times.modtime = nt_time_to_unix(newstats.dos.write_time); change_mask |= FILE_NOTIFY_CHANGE_LAST_WRITE; } - if (unix_times.actime != 0 || unix_times.modtime != 0) { - if (utime(name->full_name, &unix_times) == -1) { - return pvfs_map_errno(pvfs, errno); + if ((change_mask & FILE_NOTIFY_CHANGE_LAST_ACCESS) || + (change_mask & FILE_NOTIFY_CHANGE_LAST_WRITE)) { + struct timeval tv[2]; + + nttime_to_timeval(&tv[0], newstats.dos.access_time); + nttime_to_timeval(&tv[1], newstats.dos.write_time); + + if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) { + if (utimes(name->full_name, tv) == -1) { + DEBUG(0,("pvfs_setpathinfo: utimes() failed '%s' - %s\n", + name->full_name, strerror(errno))); + return pvfs_map_errno(pvfs, errno); + } + } + } + if (change_mask & FILE_NOTIFY_CHANGE_LAST_WRITE) { + if (lck == NULL) { + DATA_BLOB lkey; + status = pvfs_locking_key(name, name, &lkey); + NT_STATUS_NOT_OK_RETURN(status); + + lck = odb_lock(req, pvfs->odb_context, &lkey); + data_blob_free(&lkey); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for write time update\n")); + return NT_STATUS_INTERNAL_ERROR; + } + } + + status = odb_set_write_time(lck, newstats.dos.write_time, true); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + /* it could be that nobody has opened the file */ + } else if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update write time: %s\n", + nt_errstr(status))); + return status; } } diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index 4cb47a4f1f..6a57041770 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -201,7 +201,10 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, unl->unlink.in.pattern, - PVFS_RESOLVE_WILDCARD | PVFS_RESOLVE_STREAMS, &name); + PVFS_RESOLVE_WILDCARD | + PVFS_RESOLVE_STREAMS | + PVFS_RESOLVE_NO_OPENDB, + &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -246,7 +249,9 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, /* get a pvfs_filename object */ status = pvfs_resolve_partial(pvfs, req, pvfs_list_unix_path(dir), - fname, &name); + fname, + PVFS_RESOLVE_NO_OPENDB, + &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index 1f662f13fc..2da0e4bb3a 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -22,7 +22,60 @@ #include "includes.h" #include "vfs_posix.h" #include "librpc/gen_ndr/security.h" +#include "lib/events/events.h" +static void pvfs_write_time_update_handler(struct event_context *ev, + struct timed_event *te, + struct timeval tv, + void *private_data) +{ + struct pvfs_file_handle *h = talloc_get_type(private_data, + struct pvfs_file_handle); + struct odb_lock *lck; + NTSTATUS status; + NTTIME write_time; + + lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for write time update\n")); + return; + } + + write_time = timeval_to_nttime(&tv); + + status = odb_set_write_time(lck, write_time, false); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to update write time: %s\n", + nt_errstr(status))); + return; + } + + talloc_free(lck); + + h->write_time.update_event = NULL; +} + +static void pvfs_trigger_write_time_update(struct pvfs_file_handle *h) +{ + struct pvfs_state *pvfs = h->pvfs; + struct timeval tv; + + if (h->write_time.update_triggered) { + return; + } + + tv = timeval_current_ofs(0, pvfs->writetime_delay); + + h->write_time.update_triggered = true; + h->write_time.update_on_close = true; + h->write_time.update_event = event_add_timed(pvfs->ntvfs->ctx->event_ctx, + h, tv, + pvfs_write_time_update_handler, + h); + if (!h->write_time.update_event) { + DEBUG(0,("Failed event_add_timed\n")); + } +} /* write to a file @@ -61,6 +114,8 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, status = pvfs_break_level2_oplocks(f); NT_STATUS_NOT_OK_RETURN(status); + pvfs_trigger_write_time_update(f->handle); + if (f->handle->name->stream_name) { ret = pvfs_stream_write(pvfs, f->handle, diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index 14b5210fd0..b5dd270346 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -95,6 +95,10 @@ static void pvfs_setup_options(struct pvfs_state *pvfs) PVFS_OPLOCK_TIMEOUT, PVFS_OPLOCK_TIMEOUT_DEFAULT); + pvfs->writetime_delay = share_int_option(scfg, + PVFS_WRITETIME_DELAY, + PVFS_WRITETIME_DELAY_DEFAULT); + pvfs->share_name = talloc_strdup(pvfs, scfg->name); pvfs->fs_attribs = diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index c194698b64..cf39bcf0ac 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -59,6 +59,9 @@ struct pvfs_state { /* the oplock break timeout (secs) */ uint_t oplock_break_timeout; + /* the write time update delay (nsecs) */ + uint_t writetime_delay; + /* filesystem attributes (see FS_ATTR_*) */ uint32_t fs_attribs; @@ -169,6 +172,14 @@ struct pvfs_file_handle { /* we need this hook back to our parent for lock destruction */ struct pvfs_state *pvfs; + struct { + bool update_triggered; + struct timed_event *update_event; + bool update_on_close; + NTTIME close_time; + bool update_forced; + } write_time; + /* the open went through to completion */ bool open_completed; }; @@ -220,6 +231,7 @@ struct pvfs_search_state { /* flags to pvfs_resolve_name() */ #define PVFS_RESOLVE_WILDCARD (1<<0) #define PVFS_RESOLVE_STREAMS (1<<1) +#define PVFS_RESOLVE_NO_OPENDB (1<<2) /* flags in pvfs->flags */ #define PVFS_FLAG_CI_FILESYSTEM (1<<0) /* the filesystem is case insensitive */ @@ -249,6 +261,7 @@ struct pvfs_odb_retry; #define PVFS_FAKE_OPLOCKS "posix:fakeoplocks" #define PVFS_SHARE_DELAY "posix:sharedelay" #define PVFS_OPLOCK_TIMEOUT "posix:oplocktimeout" +#define PVFS_WRITETIME_DELAY "posix:writetimeupdatedelay" #define PVFS_ALLOCATION_ROUNDING "posix:allocationrounding" #define PVFS_SEARCH_INACTIVITY "posix:searchinactivity" #define PVFS_ACL "posix:acl" @@ -258,6 +271,7 @@ struct pvfs_odb_retry; #define PVFS_FAKE_OPLOCKS_DEFAULT false #define PVFS_SHARE_DELAY_DEFAULT 1000000 /* nsecs */ #define PVFS_OPLOCK_TIMEOUT_DEFAULT 30 /* secs */ +#define PVFS_WRITETIME_DELAY_DEFAULT 2000000 /* nsecs */ #define PVFS_ALLOCATION_ROUNDING_DEFAULT 512 #define PVFS_SEARCH_INACTIVITY_DEFAULT 300 diff --git a/source4/samba4-knownfail b/source4/samba4-knownfail index 67d4a4f629..ded7922ec9 100644 --- a/source4/samba4-knownfail +++ b/source4/samba4-knownfail @@ -5,7 +5,6 @@ # a successful run for any of these tests an error. local.resolve.*.async local.iconv.*.next_codepoint() -base.delaywrite.finfo update on close base.delete.*.deltest20a base.delete.*.deltest20b rpc.winreg.*security diff --git a/source4/samba4-skip b/source4/samba4-skip index 7a6c54e9ec..bf25172c76 100644 --- a/source4/samba4-skip +++ b/source4/samba4-skip @@ -14,7 +14,6 @@ # # Please add a comment for each testsuite you disable explaining why # it is being skipped. -base.delaywrite raw.composite base.iometer base.casetable @@ -28,7 +27,6 @@ samba4.ntvfs.cifs.raw.qfileinfo.ipc smb2.notify smb2.scan ntvfs.cifs.base.charset -ntvfs.cifs.base.delaywrite ntvfs.cifs.base.iometer ntvfs.cifs.base.casetable ntvfs.cifs.base.nttrans diff --git a/source4/selftest/samba4_tests.sh b/source4/selftest/samba4_tests.sh index b73ba55586..1d550cbfe1 100755 --- a/source4/selftest/samba4_tests.sh +++ b/source4/selftest/samba4_tests.sh @@ -213,7 +213,11 @@ done plantest "rpc.echo on ncacn_np over smb2" dc $smb4torture ncacn_np:"\$SERVER[smb2]" -U"\$USERNAME"%"\$PASSWORD" -W \$DOMAIN RPC-ECHO "$*" # Tests against the NTVFS POSIX backend -NTVFSARGS="--option=torture:sharedelay=100000 --option=torture:oplocktimeout=3" +NTVFSARGS="" +NTVFSARGS="${NTVFSARGS} --option=torture:sharedelay=100000" +NTVFSARGS="${NTVFSARGS} --option=torture:oplocktimeout=3" +NTVFSARGS="${NTVFSARGS} --option=torture:writetimeupdatedelay=500000" + smb2=`$smb4torture --list | grep "^SMB2-" | xargs` #The QFILEINFO-IPC test needs to be on ipc$ raw=`$smb4torture --list | grep "^RAW-" | grep -v "RAW-QFILEINFO-IPC"| xargs` diff --git a/source4/selftest/target/Samba4.pm b/source4/selftest/target/Samba4.pm index 9f771ab8a3..bcee926481 100644 --- a/source4/selftest/target/Samba4.pm +++ b/source4/selftest/target/Samba4.pm @@ -581,6 +581,7 @@ sub provision($$$$$$) posix:sharedelay = 100000 posix:eadb = $lockdir/eadb.tdb posix:oplocktimeout = 3 + posix:writetimeupdatedelay = 500000 [test1] path = $tmpdir/test1 @@ -589,6 +590,7 @@ sub provision($$$$$$) posix:sharedelay = 100000 posix:eadb = $lockdir/eadb.tdb posix:oplocktimeout = 3 + posix:writetimeupdatedelay = 500000 [test2] path = $tmpdir/test2 @@ -597,6 +599,7 @@ sub provision($$$$$$) posix:sharedelay = 100000 posix:eadb = $lockdir/eadb.tdb posix:oplocktimeout = 3 + posix:writetimeupdatedelay = 500000 [cifs] read only = no diff --git a/source4/setup/setpassword b/source4/setup/setpassword index 65770e1f4d..65770e1f4d 100644..100755 --- a/source4/setup/setpassword +++ b/source4/setup/setpassword diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c index e5ba814cb2..711c86bb74 100644 --- a/source4/smb_server/smb/trans2.c +++ b/source4/smb_server/smb/trans2.c @@ -588,12 +588,20 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req, case RAW_SFILEINFO_UNIX_BASIC: case RAW_SFILEINFO_UNIX_LINK: case RAW_SFILEINFO_UNIX_HLINK: - case RAW_SFILEINFO_1023: + case RAW_SFILEINFO_PIPE_INFORMATION: + case RAW_SFILEINFO_VALID_DATA_INFORMATION: + case RAW_SFILEINFO_SHORT_NAME_INFORMATION: case RAW_SFILEINFO_1025: + case RAW_SFILEINFO_1027: case RAW_SFILEINFO_1029: + case RAW_SFILEINFO_1030: + case RAW_SFILEINFO_1031: case RAW_SFILEINFO_1032: - case RAW_SFILEINFO_1039: - case RAW_SFILEINFO_1040: + case RAW_SFILEINFO_1036: + case RAW_SFILEINFO_1041: + case RAW_SFILEINFO_1042: + case RAW_SFILEINFO_1043: + case RAW_SFILEINFO_1044: return NT_STATUS_INVALID_LEVEL; default: @@ -784,6 +792,7 @@ static NTSTATUS find_fill_info(struct find_state *state, SMBSRV_REQ_DEFAULT_STR_FLAGS(req)); case RAW_SEARCH_DATA_UNIX_INFO: + case RAW_SEARCH_DATA_UNIX_INFO2: return NT_STATUS_INVALID_LEVEL; } diff --git a/source4/smb_server/smb2/fileinfo.c b/source4/smb_server/smb2/fileinfo.c index 942000133c..6c4b8f33d5 100644 --- a/source4/smb_server/smb2/fileinfo.c +++ b/source4/smb_server/smb2/fileinfo.c @@ -53,6 +53,11 @@ static void smb2srv_getinfo_send(struct ntvfs_request *ntvfs) SMB2SRV_CHECK(op->send_fn(op)); } + if (op->info->in.output_buffer_length < op->info->out.blob.length) { + smb2srv_send_error(req, NT_STATUS_INFO_LENGTH_MISMATCH); + return; + } + SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, op->info->out.blob.length)); SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, op->info->out.blob)); diff --git a/source4/smb_server/smb2/tcon.c b/source4/smb_server/smb2/tcon.c index 040947f84f..be64013bb2 100644 --- a/source4/smb_server/smb2/tcon.c +++ b/source4/smb_server/smb2/tcon.c @@ -327,7 +327,7 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req, req->session->session_info, - 0, /* TODO: fill in PID */ + SVAL(req->in.hdr, SMB2_HDR_PID), req->request_time, req, NULL, 0); if (!req->ntvfs) { diff --git a/source4/torture/basic/delaywrite.c b/source4/torture/basic/delaywrite.c index 84adfef61a..c03e89d36e 100644 --- a/source4/torture/basic/delaywrite.c +++ b/source4/torture/basic/delaywrite.c @@ -641,7 +641,7 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s bool err = false; \ if (strict && (g cmp c)) { \ err = true; \ - } else if (gr cmp cr) { \ + } else if ((g cmp c) && (gr cmp cr)) { \ /* handle filesystem without high resolution timestamps */ \ err = true; \ } \ @@ -673,23 +673,11 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s } while (0) #define COMPARE_ACCESS_TIME_EQUAL(given,correct) \ COMPARE_ACCESS_TIME_CMP(given,correct,!=) -#define COMPARE_ACCESS_TIME_GREATER(given,correct) \ - COMPARE_ACCESS_TIME_CMP(given,correct,<=) -#define COMPARE_ACCESS_TIME_LESS(given,correct) \ - COMPARE_ACCESS_TIME_CMP(given,correct,>=) #define COMPARE_BOTH_TIMES_EQUAL(given,correct) do { \ COMPARE_ACCESS_TIME_EQUAL(given,correct); \ COMPARE_WRITE_TIME_EQUAL(given,correct); \ } while (0) -#define COMPARE_BOTH_TIMES_GEATER(given,correct) do { \ - COMPARE_ACCESS_TIME_GREATER(given,correct); \ - COMPARE_WRITE_TIME_GREATER(given,correct); \ -} while (0) -#define COMPARE_BOTH_TIMES_LESS(given,correct) do { \ - COMPARE_ACCESS_TIME_LESS(given,correct); \ - COMPARE_WRITE_TIME_LESS(given,correct); \ -} while (0) #define GET_INFO_FILE(finfo) do { \ NTSTATUS _status; \ @@ -828,6 +816,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx, } GET_INFO_BOTH(finfo1,pinfo1); + COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0); /* sure any further write doesn't update the write time */ start = timeval_current(); @@ -982,6 +971,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx, } GET_INFO_BOTH(finfo1,pinfo1); + COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0); /* sure any further write doesn't update the write time */ start = timeval_current(); diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 07d394fad6..60243a5d1b 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -2199,16 +2199,20 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info) LVL(STANDARD), LVL(ALLOCATION_INFO), LVL(END_OF_FILE_INFO), LVL(SETATTR), LVL(SETATTRE), LVL(BASIC_INFORMATION), LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION), - LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION), + LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION), LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION), - LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040), + LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION), + LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036), + LVL(1041), LVL(1042), LVL(1043), LVL(1044), }; struct levels smb2_levels[] = { LVL(BASIC_INFORMATION), LVL(RENAME_INFORMATION), LVL(DISPOSITION_INFORMATION), - LVL(POSITION_INFORMATION), LVL(MODE_INFORMATION), + LVL(POSITION_INFORMATION), LVL(FULL_EA_INFORMATION), LVL(MODE_INFORMATION), LVL(ALLOCATION_INFORMATION), LVL(END_OF_FILE_INFORMATION), - LVL(1023), LVL(1025), LVL(1029), LVL(1032), LVL(1039), LVL(1040) + LVL(PIPE_INFORMATION), LVL(VALID_DATA_INFORMATION), LVL(SHORT_NAME_INFORMATION), + LVL(1025), LVL(1027), LVL(1029), LVL(1030), LVL(1031), LVL(1032), LVL(1036), + LVL(1041), LVL(1042), LVL(1043), LVL(1044), }; struct levels *levels = options.smb2?smb2_levels:smb_levels; uint32_t num_levels = options.smb2?ARRAY_SIZE(smb2_levels):ARRAY_SIZE(smb_levels); @@ -2276,12 +2280,9 @@ static void gen_setfileinfo(int instance, union smb_setfileinfo *info) case RAW_SFILEINFO_GENERIC: case RAW_SFILEINFO_SEC_DESC: - case RAW_SFILEINFO_1023: case RAW_SFILEINFO_1025: case RAW_SFILEINFO_1029: case RAW_SFILEINFO_1032: - case RAW_SFILEINFO_1039: - case RAW_SFILEINFO_1040: case RAW_SFILEINFO_UNIX_BASIC: case RAW_SFILEINFO_UNIX_INFO2: case RAW_SFILEINFO_UNIX_LINK: diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c index 1c3274adcd..bf53df4a11 100644 --- a/source4/torture/local/local.c +++ b/source4/torture/local/local.c @@ -68,16 +68,13 @@ NTSTATUS torture_local_init(void) torture_suite_add_simple_test(suite, "TALLOC", torture_local_talloc); torture_suite_add_simple_test(suite, "REPLACE", torture_local_replace); - torture_suite_add_simple_test(suite, "CRYPTO-SHA1", - torture_local_crypto_sha1); torture_suite_add_simple_test(suite, "CRYPTO-MD4", torture_local_crypto_md4); torture_suite_add_simple_test(suite, "CRYPTO-MD5", torture_local_crypto_md5); torture_suite_add_simple_test(suite, "CRYPTO-HMACMD5", torture_local_crypto_hmacmd5); - torture_suite_add_simple_test(suite, "CRYPTO-HMACSHA1", - torture_local_crypto_hmacsha1); + for (i = 0; suite_generators[i]; i++) torture_suite_add_suite(suite, suite_generators[i](talloc_autofree_context())); diff --git a/source4/torture/nbench/nbench.c b/source4/torture/nbench/nbench.c index 96144c4773..5a4037f906 100644 --- a/source4/torture/nbench/nbench.c +++ b/source4/torture/nbench/nbench.c @@ -23,7 +23,6 @@ #include "torture/smbtorture.h" #include "system/filesys.h" #include "system/locale.h" -#include "pstring.h" #include "torture/nbench/proto.h" @@ -59,7 +58,7 @@ static bool run_netbench(struct torture_context *tctx, struct smbcli_state *cli, { int torture_nprocs = torture_setting_int(tctx, "nprocs", 4); int i; - pstring line; + char line[1024]; char *cname; FILE *f; bool correct = true; diff --git a/source4/torture/smb2/getinfo.c b/source4/torture/smb2/getinfo.c index 906d6e4f8d..5b35d7e693 100644 --- a/source4/torture/smb2/getinfo.c +++ b/source4/torture/smb2/getinfo.c @@ -167,6 +167,40 @@ static bool torture_smb2_fsinfo(struct smb2_tree *tree) } +/* + test for buffer size handling +*/ +static bool torture_smb2_buffercheck(struct smb2_tree *tree) +{ + NTSTATUS status; + struct smb2_handle handle; + struct smb2_getinfo b; + + printf("Testing buffer size handling\n"); + status = smb2_util_roothandle(tree, &handle); + if (!NT_STATUS_IS_OK(status)) { + printf(__location__ " Unable to create root handle - %s\n", nt_errstr(status)); + return false; + } + + ZERO_STRUCT(b); + b.in.info_type = SMB2_GETINFO_FS; + b.in.info_class = 1; + b.in.output_buffer_length = 0x1; + b.in.input_buffer_length = 0; + b.in.file.handle = handle; + + status = smb2_getinfo(tree, tree, &b); + if (!NT_STATUS_EQUAL(status, NT_STATUS_INFO_LENGTH_MISMATCH)) { + printf(__location__ " Wrong error code for small buffer %s\n", + nt_errstr(status)); + return false; + } + + return true; +} + + /* basic testing of all SMB2 getinfo levels */ bool torture_smb2_getinfo(struct torture_context *torture) @@ -196,6 +230,7 @@ bool torture_smb2_getinfo(struct torture_context *torture) ret &= torture_smb2_fileinfo(torture, tree); ret &= torture_smb2_fsinfo(tree); + ret &= torture_smb2_buffercheck(tree); talloc_free(mem_ctx); diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c index 35ad839610..d820983022 100644 --- a/source4/torture/smb2/lock.c +++ b/source4/torture/smb2/lock.c @@ -268,20 +268,12 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree lck.in.lock_count = 1; el[0].flags = SMB2_LOCK_FLAG_UNLOCK; status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); - } else { - CHECK_STATUS(status, NT_STATUS_OK); - } + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); lck.in.lock_count = 1; el[0].flags = SMB2_LOCK_FLAG_UNLOCK; status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { - CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); - } else { - CHECK_STATUS(status, NT_STATUS_OK); - } + CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED); lck.in.lock_count = 1; el[0].flags = SMB2_LOCK_FLAG_UNLOCK; diff --git a/source4/torture/smb2/scan.c b/source4/torture/smb2/scan.c index 1ce796be4d..ae51af1882 100644 --- a/source4/torture/smb2/scan.c +++ b/source4/torture/smb2/scan.c @@ -77,22 +77,20 @@ bool torture_smb2_getinfo_scan(struct torture_context *torture) io.in.file.handle = fhandle; status = smb2_getinfo(tree, torture, &io); - if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && - !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) && - !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { - printf("file level 0x%02x:%02x is %ld bytes - %s\n", + if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { + printf("file level 0x%02x:%02x %u is %ld bytes - %s\n", io.in.info_type, io.in.info_class, + (unsigned)io.in.info_class, (long)io.out.blob.length, nt_errstr(status)); dump_data(1, io.out.blob.data, io.out.blob.length); } io.in.file.handle = dhandle; status = smb2_getinfo(tree, torture, &io); - if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && - !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) && - !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { - printf("dir level 0x%02x:%02x is %ld bytes - %s\n", + if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { + printf("dir level 0x%02x:%02x %u is %ld bytes - %s\n", io.in.info_type, io.in.info_class, + (unsigned)io.in.info_class, (long)io.out.blob.length, nt_errstr(status)); dump_data(1, io.out.blob.data, io.out.blob.length); } @@ -134,8 +132,7 @@ bool torture_smb2_setinfo_scan(struct torture_context *torture) io.in.level = (i<<8) | c; io.in.file.handle = handle; status = smb2_setinfo(tree, &io); - if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && - !NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { + if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) { printf("file level 0x%04x - %s\n", io.in.level, nt_errstr(status)); } diff --git a/testprogs/ejs/ldap.js b/testprogs/ejs/ldap.js index 44e4c83e67..a5e6ab37c4 100755 --- a/testprogs/ejs/ldap.js +++ b/testprogs/ejs/ldap.js @@ -486,11 +486,11 @@ sn: ldap user2 assert(res.msgs.length == 2); } - var res = ldb.search("(&(anr=testy ldap)(objectClass=user))"); - if (res.error != 0 || res.msgs.length != 2) { - println("Found only " + res.msgs.length + " for (&(anr=\"testy ldap\")(objectClass=user))"); + var res = ldb.search("(&(anr=\"testy ldap\")(objectClass=user))"); + if (res.error != 0 || res.msgs.length != 0) { + println("Found " + res.msgs.length + " for (&(anr=\"testy ldap\")(objectClass=user))"); assert(res.error == 0); - assert(res.msgs.length == 2); + assert(res.msgs.length == 0); } // Testing ldb.search for (&(anr=ldap)(objectClass=user)) |