diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-08-24 00:58:52 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:34:28 -0500 |
commit | c0ab8767118bc0e8a57bc1b31e37a261272fbc33 (patch) | |
tree | e8540742a6bc6112614233a4a11debbe6116869b /source4/lib | |
parent | cdb6d52372624b937db6b3d3cbc9353d4064af11 (diff) | |
download | samba-c0ab8767118bc0e8a57bc1b31e37a261272fbc33.tar.gz samba-c0ab8767118bc0e8a57bc1b31e37a261272fbc33.tar.bz2 samba-c0ab8767118bc0e8a57bc1b31e37a261272fbc33.zip |
r9555: More updates. Everything except for secrets.c compiles now..
(This used to be commit e59d6156b2d569ca788fe1824148f05f4a7a9918)
Diffstat (limited to 'source4/lib')
-rw-r--r-- | source4/lib/samba3/config.mk | 5 | ||||
-rw-r--r-- | source4/lib/samba3/group.c | 2 | ||||
-rw-r--r-- | source4/lib/samba3/idmap.c | 2 | ||||
-rw-r--r-- | source4/lib/samba3/policy.c | 4 | ||||
-rw-r--r-- | source4/lib/samba3/policy.h | 37 | ||||
-rw-r--r-- | source4/lib/samba3/samba3.h (renamed from source4/lib/samba3/sam.h) | 49 | ||||
-rw-r--r-- | source4/lib/samba3/samba3dump.c | 3 | ||||
-rw-r--r-- | source4/lib/samba3/secrets.c | 160 | ||||
-rw-r--r-- | source4/lib/samba3/tdbsam.c | 2 | ||||
-rw-r--r-- | source4/lib/samba3/winsdb.c | 179 |
10 files changed, 339 insertions, 104 deletions
diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk index ba6c1a8dbc..15802d3b8e 100644 --- a/source4/lib/samba3/config.mk +++ b/source4/lib/samba3/config.mk @@ -4,7 +4,10 @@ INIT_OBJ_FILES = \ lib/samba3/smbpasswd.o \ lib/samba3/tdbsam.o \ - lib/samba3/policy.o + lib/samba3/policy.o \ + lib/samba3/idmap.o \ + lib/samba3/winsdb.o +# lib/samba3/secrets.o # End SUBSYSTEM LIBSAMBA3 ################################################ diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c index b8cc0d6819..d7097f596a 100644 --- a/source4/lib/samba3/group.c +++ b/source4/lib/samba3/group.c @@ -21,7 +21,7 @@ #include "includes.h" #include "system/iconv.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "lib/tdb/include/tdbutil.h" #include "system/filesys.h" diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c index c541c5bc92..64d6387ed4 100644 --- a/source4/lib/samba3/idmap.c +++ b/source4/lib/samba3/idmap.c @@ -25,7 +25,7 @@ #include "includes.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "system/filesys.h" /* High water mark keys */ diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c index 796e6eefac..bfb3ac373e 100644 --- a/source4/lib/samba3/policy.c +++ b/source4/lib/samba3/policy.c @@ -21,7 +21,7 @@ #include "includes.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/policy.h" +#include "lib/samba3/samba3.h" #include "system/filesys.h" #define DATABASE_VERSION 2 @@ -65,3 +65,5 @@ struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn return ret; } + +/* FIXME: Read privileges as well */ diff --git a/source4/lib/samba3/policy.h b/source4/lib/samba3/policy.h deleted file mode 100644 index b41f38a394..0000000000 --- a/source4/lib/samba3/policy.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Copyright (C) Jelmer Vernooij 2005. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _SAMBA3_POLICY_H /* _SAMBA3_POLICY_H */ -#define _SAMBA3_POLICY_H - -struct samba3_policy -{ - uint32_t min_password_length; - uint32_t password_history; - uint32_t user_must_logon_to_change_password; - uint32_t maximum_password_age; - uint32_t minimum_password_age; - uint32_t lockout_duration; - uint32_t reset_count_minutes; - uint32_t bad_lockout_minutes; - uint32_t disconnect_time; - uint32_t refuse_machine_password_change; -}; - -#endif /* _SAMBA3_POLICY_H */ diff --git a/source4/lib/samba3/sam.h b/source4/lib/samba3/samba3.h index bc13b28e2a..d3e03cf923 100644 --- a/source4/lib/samba3/sam.h +++ b/source4/lib/samba3/samba3.h @@ -1,6 +1,6 @@ /* Unix SMB/CIFS implementation. - Registry interface + Samba3 interfaces Copyright (C) Jelmer Vernooij 2005. This program is free software; you can redistribute it and/or modify @@ -18,8 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _SAMBA3_SAM_H /* _SAMBA3_SAM_H */ -#define _SAMBA3_SAM_H +#ifndef _SAMBA3_H /* _SAMBA3_H */ +#define _SAMBA3_H #include "librpc/gen_ndr/security.h" @@ -75,4 +75,45 @@ struct samba3_groupmapping { const char *comment; }; -#endif /* _SAMBA3_SAM_H */ +struct samba3_idmap_mapping +{ + enum { IDMAP_GROUP, IDMAP_USER } type; + uint32_t unix_id; + struct dom_sid *sid; +}; + +struct samba3_idmap +{ + /* High water marks */ + uint32_t user_hwm; + uint32_t group_hwm; + + uint32_t mapping_count; + struct samba3_idmap_mapping *mappings; +}; + +struct samba3_winsdb_entry +{ + char *name; + int nb_flags; + int type; + time_t ttl; + uint32_t ip_count; + struct ipv4_addr *ips; +}; + +struct samba3_policy +{ + uint32_t min_password_length; + uint32_t password_history; + uint32_t user_must_logon_to_change_password; + uint32_t maximum_password_age; + uint32_t minimum_password_age; + uint32_t lockout_duration; + uint32_t reset_count_minutes; + uint32_t bad_lockout_minutes; + uint32_t disconnect_time; + uint32_t refuse_machine_password_change; +}; + +#endif /* _SAMBA3_H */ diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c index 72052092ff..6bcfce96fa 100644 --- a/source4/lib/samba3/samba3dump.c +++ b/source4/lib/samba3/samba3dump.c @@ -20,8 +20,7 @@ */ #include "includes.h" -#include "lib/samba3/policy.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #include "lib/cmdline/popt_common.h" static const char *libdir = "/var/lib/samba"; diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c index ccd53c0398..ab19f166ee 100644 --- a/source4/lib/samba3/secrets.c +++ b/source4/lib/samba3/secrets.c @@ -42,6 +42,7 @@ #include "tdb.h" #include "system/filesys.h" #include "librpc/gen_ndr/ndr_security.h" +#include "lib/tdb/include/tdbutil.h" /* structure for storing machine account password (ie. when samba server is member of a domain */ @@ -57,6 +58,78 @@ struct afs_key { char key[8]; }; +/* + * storage structure for trusted domain + */ +typedef struct trusted_dom_pass { + size_t uni_name_len; + const char *uni_name[32]; /* unicode domain name */ + size_t pass_len; + const char *pass; /* trust relationship's password */ + time_t mod_time; + struct dom_sid domain_sid; /* remote domain's sid */ +} TRUSTED_DOM_PASS; + +/** + * Unpack SID into a pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param sid pointer to sid structure to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid) +{ + int idx, len = 0; + + if (!sid || !pack_buf) return -1; + + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb", + &sid->sid_rev_num, &sid->num_auths); + + for (idx = 0; idx < 6; idx++) { + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]); + } + + for (idx = 0; idx < 15; idx++) { + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]); + } + + return len; +} + +/** + * Unpack TRUSTED_DOM_PASS passed by pointer + * + * @param pack_buf pointer to buffer with packed representation + * @param bufsize size of the buffer + * @param pass pointer to trusted domain password to be filled with unpacked data + * + * @return size of structure unpacked from buffer + **/ +static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass) +{ + int idx, len = 0; + + if (!pack_buf || !pass) return -1; + + /* unpack unicode domain name and plaintext password */ + len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len); + + for (idx = 0; idx < 32; idx++) + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]); + + len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass, + &pass->mod_time); + + /* unpack domain sid */ + len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid); + + return len; +} + + static TDB_CONTEXT *secrets_open(const char *fname) { TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600); @@ -69,31 +142,18 @@ static TDB_CONTEXT *secrets_open(const char *fname) return tdb; } -/* read a entry from the secrets database - the caller must free the result - if size is non-null then the size of the entry is put in there - */ -static void *secrets_fetch(TDB_CONTEXT *tdb, const char *key, size_t *size) -{ - TDB_DATA kbuf, dbuf; - - kbuf.dptr = strdup(key); - kbuf.dsize = strlen(key); - dbuf = tdb_fetch(tdb, kbuf); - if (size) - *size = dbuf.dsize; - free(kbuf.dptr); - return dbuf.dptr; -} - static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid) { struct dom_sid *dyn_sid; + TDB_DATA val; char *key; size_t size; asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain); strupper_m(key); - dyn_sid = (struct dom_sid *)secrets_fetch(tdb, key, &size); + + val = tdb_fetch_bystring(tdb, key); + /* FIXME: Convert val to dyn_sid */ SAFE_FREE(key); if (dyn_sid == NULL) @@ -114,17 +174,20 @@ static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, stru { struct GUID *dyn_guid; char *key; + TDB_DATA val; size_t size; asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); - dyn_guid = (struct GUID *)secrets_fetch(tdb, key, &size); + val = tdb_fetch_bystring(tdb, key); + + dyn_guid = (struct GUID *)val.dptr; if (!dyn_guid) { return False; } - if (size != sizeof(struct GUID)) + if (val.dsize != sizeof(struct GUID)) { DEBUG(1,("GUID size %d is wrong!\n", (int)size)); SAFE_FREE(dyn_guid); @@ -183,7 +246,7 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, { struct machine_acct_pass *pass; char *plaintext; - size_t size; + TDB_DATA val; plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, channel); @@ -193,23 +256,22 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, SAFE_FREE(plaintext); return True; } - - if (!(pass = secrets_fetch(tdb, trust_keystr(domain), &size))) { - DEBUG(5, ("secrets_fetch failed!\n")); + + val = tdb_fetch_bystring(tdb, trust_keystr(domain)); + if (!val.dptr) { + DEBUG(5, ("tdb_fetch_bystring failed!\n")); return False; } - if (size != sizeof(*pass)) { + if (val.dsize != sizeof(*pass)) { DEBUG(0, ("secrets were of incorrect size!\n")); return False; } + pass = (struct machine_acct_pass *)val.dptr; + if (pass_last_set_time) *pass_last_set_time = pass->mod_time; memcpy(ret_pwd, pass->hash, 16); - SAFE_FREE(pass); - - if (channel) - *channel = get_default_sec_channel(); return True; } @@ -221,25 +283,24 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb, static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time) { struct trusted_dom_pass pass; - size_t size; /* unpacking structures */ - char* pass_buf; int pass_len = 0; + TDB_DATA val; ZERO_STRUCT(pass); /* fetching trusted domain password structure */ - if (!(pass_buf = secrets_fetch(tdb, trustdom_keystr(domain), &size))) { + val = tdb_fetch_bystring(tdb, trustdom_keystr(domain)); + if (!val.dptr) { DEBUG(5, ("secrets_fetch failed!\n")); return False; } /* unpack trusted domain password */ - pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass); - SAFE_FREE(pass_buf); + pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass); - if (pass_len != size) { + if (pass_len != val.dsize) { DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n")); return False; } @@ -272,38 +333,23 @@ static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain { char *key = NULL; char *ret; + TDB_DATA val; asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); strupper_m(key); - ret = (char *)secrets_fetch(tdb, key, NULL); + val = tdb_fetch_bystring(tdb, key); SAFE_FREE(key); if (pass_last_set_time) { - size_t size; - uint32_t *last_set_time; asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); strupper_m(key); - last_set_time = secrets_fetch(tdb, key, &size); - if (last_set_time) { - *pass_last_set_time = IVAL(last_set_time,0); - SAFE_FREE(last_set_time); - } else { - *pass_last_set_time = 0; - } + tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time); SAFE_FREE(key); } if (channel) { - size_t size; - uint32_t *channel_type; asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); strupper_m(key); - channel_type = secrets_fetch(tdb, key, &size); - if (channel_type) { - *channel = IVAL(channel_type,0); - SAFE_FREE(channel_type); - } else { - *channel = get_default_sec_channel(); - } + tdb_fetch_uint32(tdb, key, channel); SAFE_FREE(key); } @@ -317,12 +363,14 @@ static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw) { char *key = NULL; size_t size; + TDB_DATA val; if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) { DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); } - *pw=secrets_fetch(tdb, key, &size); + val = tdb_fetch_bystring(tdb, key); + *pw = val.dptr; SAFE_FREE(key); if (!size) { @@ -363,8 +411,6 @@ static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, i struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass); NTSTATUS status; - if (!secrets_init()) return NT_STATUS_ACCESS_DENIED; - if (!pass) { DEBUG(0, ("talloc_zero failed!\n")); return NT_STATUS_NO_MEMORY; @@ -540,3 +586,5 @@ static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char * *password = smb_xstrdup(""); } } + + diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c index a16c07d2d1..aba01d0db6 100644 --- a/source4/lib/samba3/tdbsam.c +++ b/source4/lib/samba3/tdbsam.c @@ -28,7 +28,7 @@ #include "system/iconv.h" #include "system/filesys.h" #include "lib/tdb/include/tdbutil.h" -#include "lib/samba3/sam.h" +#include "lib/samba3/samba3.h" #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" diff --git a/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c new file mode 100644 index 0000000000..7c3253e101 --- /dev/null +++ b/source4/lib/samba3/winsdb.c @@ -0,0 +1,179 @@ +/* + Unix SMB/CIFS implementation. + Wins Database + + Copyright (C) Jeremy Allison 1994-2003 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "pstring.h" +#include "lib/samba3/samba3.h" + +#define WINS_VERSION 1 + +NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_winsdb_entry **entries, uint32_t *count ) +{ + XFILE *fp; + char *line; + + if((fp = x_fopen(fn,O_RDONLY,0)) == NULL) { + DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", + fn, strerror(errno) )); + return NT_STATUS_UNSUCCESSFUL; + } + + *count = 0; + *entries = NULL; + + while (!x_feof(fp)) { + struct samba3_winsdb_entry entry; + pstring name_str, ip_str, ttl_str, nb_flags_str; + const char *ptr; + char *p; + BOOL got_token; + BOOL was_ip; + int i; + unsigned int hash; + int version; + + /* Read a line from the wins.dat file. Strips whitespace + from the beginning and end of the line. */ + line = fgets_slash(NULL,-1,fp); + if (!line) + return NT_STATUS_UNSUCCESSFUL; + + if (*line == '#') { + SAFE_FREE(line); + continue; + } + + if (strncmp(line,"VERSION ", 8) == 0) { + if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || + version != WINS_VERSION) { + DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); + SAFE_FREE(line); + x_fclose(fp); + return NT_STATUS_UNSUCCESSFUL; + } + SAFE_FREE(line); + + continue; + } + + ptr = line; + + /* + * Now we handle multiple IP addresses per name we need + * to iterate over the line twice. The first time to + * determine how many IP addresses there are, the second + * time to actually parse them into the ip_list array. + */ + + if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { + DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { + DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + /* + * Determine the number of IP addresses per line. + */ + entry.ip_count = 0; + do { + got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); + was_ip = False; + + if(got_token && strchr(ip_str, '.')) { + entry.ip_count++; + was_ip = True; + } + } while( got_token && was_ip); + + if(entry.ip_count == 0) { + DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + if(!got_token) { + DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); + SAFE_FREE(line); + continue; + } + + /* Allocate the space for the ip_list. */ + if((entry.ips = talloc_array ( ctx, struct ipv4_addr, entry.ip_count)) == NULL) { + DEBUG(0,("initialise_wins: Malloc fail !\n")); + SAFE_FREE(line); + return NT_STATUS_NO_MEMORY; + } + + /* Reset and re-parse the line. */ + ptr = line; + next_token(&ptr,name_str,NULL,sizeof(name_str)); + next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); + for(i = 0; i < entry.ip_count; i++) { + next_token(&ptr, ip_str, NULL, sizeof(ip_str)); + entry.ips[i] = interpret_addr2(ip_str); + } + next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); + + /* + * Deal with SELF or REGISTER name encoding. Default is REGISTER + * for compatibility with old nmbds. + */ + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { + DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); + talloc_free(entry.ips); + SAFE_FREE(line); + continue; + } + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') + nb_flags_str[strlen(nb_flags_str)-1] = '\0'; + + /* Netbios name. # divides the name from the type (hex): netbios#xx */ + entry.name = talloc_strdup(ctx, name_str); + + if((p = strchr(entry.name,'#')) != NULL) { + *p = 0; + sscanf(p+1,"%x",&entry.type); + } + + /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ + sscanf(nb_flags_str,"%x",&entry.nb_flags); + entry.ttl = atol(ttl_str); + + *entries = talloc_realloc(ctx, *entries, struct samba3_winsdb_entry, (*count)+1); + *entries[*count] = entry; + + (*count)++; + } + + x_fclose(fp); + return NT_STATUS_OK; +} |