summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/net.c79
-rw-r--r--source3/utils/net_cache.c56
-rw-r--r--source3/utils/net_rpc.c7
-rw-r--r--source3/utils/ntlm_auth.c429
-rw-r--r--source3/utils/pdbedit.c5
-rw-r--r--source3/utils/profiles.c729
-rw-r--r--source3/utils/smbcontrol.c2
-rw-r--r--source3/utils/smbfilter.c1
-rw-r--r--source3/utils/testparm.c1
-rw-r--r--source3/utils/testprns.c1
10 files changed, 26 insertions, 1284 deletions
diff --git a/source3/utils/net.c b/source3/utils/net.c
index ba08feae19..37ceadc372 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -389,84 +389,6 @@ static int net_getdomainsid(int argc, const char **argv)
return 0;
}
-static uint32 get_maxrid(void)
-{
- SAM_ACCOUNT *pwd = NULL;
- uint32 max_rid = 0;
- GROUP_MAP *map = NULL;
- int num_entries = 0;
- int i;
-
- if (!pdb_setsampwent(False)) {
- DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
- return 0;
- }
-
- for (; (NT_STATUS_IS_OK(pdb_init_sam(&pwd)))
- && pdb_getsampwent(pwd) == True; pwd=NULL) {
- uint32 rid;
-
- if (!sid_peek_rid(pdb_get_user_sid(pwd), &rid)) {
- DEBUG(0, ("can't get RID for user '%s'\n",
- pdb_get_username(pwd)));
- pdb_free_sam(&pwd);
- continue;
- }
-
- if (rid > max_rid)
- max_rid = rid;
-
- DEBUG(1,("%d is user '%s'\n", rid, pdb_get_username(pwd)));
- pdb_free_sam(&pwd);
- }
-
- pdb_endsampwent();
- pdb_free_sam(&pwd);
-
- if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries,
- ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
- return max_rid;
-
- for (i = 0; i < num_entries; i++) {
- uint32 rid;
-
- if (!sid_peek_check_rid(get_global_sam_sid(), &map[i].sid,
- &rid)) {
- DEBUG(3, ("skipping map for group '%s', SID %s\n",
- map[i].nt_name,
- sid_string_static(&map[i].sid)));
- continue;
- }
- DEBUG(1,("%d is group '%s'\n", rid, map[i].nt_name));
-
- if (rid > max_rid)
- max_rid = rid;
- }
-
- SAFE_FREE(map);
-
- return max_rid;
-}
-
-static int net_maxrid(int argc, const char **argv)
-{
- uint32 rid;
-
- if (argc != 0) {
- DEBUG(0, ("usage: net initrid\n"));
- return 1;
- }
-
- if ((rid = get_maxrid()) == 0) {
- DEBUG(0, ("can't get current maximum rid\n"));
- return 1;
- }
-
- d_printf("Currently used maximum rid: %d\n", rid);
-
- return 0;
-}
-
/* main function table */
static struct functable net_func[] = {
{"RPC", net_rpc},
@@ -494,7 +416,6 @@ static struct functable net_func[] = {
{"GETLOCALSID", net_getlocalsid},
{"SETLOCALSID", net_setlocalsid},
{"GETDOMAINSID", net_getdomainsid},
- {"MAXRID", net_maxrid},
{"HELP", net_help},
{NULL, NULL}
diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c
index 93c4f1aa1d..359c06d1aa 100644
--- a/source3/utils/net_cache.c
+++ b/source3/utils/net_cache.c
@@ -34,34 +34,15 @@
* (print_cache_entry) and to flush it (delete_cache_entry).
* Both of them are defined by first arg of gencache_iterate() routine.
*/
-static void print_cache_entry(const char* keystr, const char* datastr,
- const time_t timeout, void* dptr)
+static void print_cache_entry(const char* keystr, const char* datastr, const time_t timeout)
{
- char* timeout_str;
- time_t now_t = time(NULL);
- struct tm timeout_tm, *now_tm;
- /* localtime returns statically allocated pointer, so timeout_tm
- has to be copied somewhere else */
- memcpy(&timeout_tm, localtime(&timeout), sizeof(struct tm));
- now_tm = localtime(&now_t);
-
- /* form up timeout string depending whether it's today's date or not */
- if (timeout_tm.tm_year != now_tm->tm_year ||
- timeout_tm.tm_mon != now_tm->tm_mon ||
- timeout_tm.tm_mday != now_tm->tm_mday) {
-
- timeout_str = asctime(&timeout_tm);
- timeout_str[strlen(timeout_str) - 1] = '\0'; /* remove tailing CR */
- } else
- asprintf(&timeout_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour,
- timeout_tm.tm_min, timeout_tm.tm_sec);
-
- d_printf("Key: %s\t Timeout: %s\t Value: %s %s\n", keystr,
- timeout_str, datastr, timeout > now_t ? "": "(expired)");
+ char* timeout_str = ctime(&timeout);
+ timeout_str[strlen(timeout_str) - 1] = '\0';
+ d_printf("Key: %s\t\t Value: %s\t\t Timeout: %s %s\n", keystr, datastr,
+ timeout_str, timeout > time(NULL) ? "": "(expired)");
}
-static void delete_cache_entry(const char* keystr, const char* datastr,
- const time_t timeout, void* dptr)
+static void delete_cache_entry(const char* keystr, const char* datastr, const time_t timeout)
{
if (!gencache_del(keystr))
d_printf("Couldn't delete entry! key = %s", keystr);
@@ -125,7 +106,7 @@ static time_t parse_timeout(const char* timeout_str)
/**
- * Add an entry to the cache. If it does exist, then set it.
+ * Add an entry to the cache
*
* @param argv key, value and timeout are passed in command line
* @return 0 on success, otherwise failure
@@ -151,12 +132,12 @@ static int net_cache_add(int argc, const char **argv)
return -1;
}
- if (gencache_set(keystr, datastr, timeout)) {
+ if (gencache_add(keystr, datastr, timeout)) {
d_printf("New cache entry stored successfully.\n");
gencache_shutdown();
return 0;
- }
-
+ }
+
d_printf("Entry couldn't be added. Perhaps there's already such a key.\n");
gencache_shutdown();
return -1;
@@ -164,8 +145,7 @@ static int net_cache_add(int argc, const char **argv)
/**
- * Set new value of an existing entry in the cache. Fail If the entry doesn't
- * exist.
+ * Set new value of an existing entry in the cache
*
* @param argv key being searched and new value and timeout to set in the entry
* @return 0 on success, otherwise failure
@@ -191,7 +171,7 @@ static int net_cache_set(int argc, const char **argv)
return -1;
}
- if (gencache_set_only(keystr, datastr, timeout)) {
+ if (gencache_set(keystr, datastr, timeout)) {
d_printf("Cache entry set successfully.\n");
gencache_shutdown();
return 0;
@@ -221,7 +201,7 @@ static int net_cache_del(int argc, const char **argv)
if(gencache_del(keystr)) {
d_printf("Entry deleted.\n");
return 0;
- }
+ }
d_printf("Couldn't delete specified entry\n");
return -1;
@@ -246,9 +226,9 @@ static int net_cache_get(int argc, const char **argv)
}
if (gencache_get(keystr, &valuestr, &timeout)) {
- print_cache_entry(keystr, valuestr, timeout, NULL);
+ print_cache_entry(keystr, valuestr, timeout);
return 0;
- }
+ }
d_printf("Failed to find entry\n");
return -1;
@@ -271,7 +251,7 @@ static int net_cache_search(int argc, const char **argv)
}
pattern = argv[0];
- gencache_iterate(print_cache_entry, NULL, pattern);
+ gencache_iterate(print_cache_entry, pattern);
return 0;
}
@@ -285,7 +265,7 @@ static int net_cache_search(int argc, const char **argv)
static int net_cache_list(int argc, const char **argv)
{
const char* pattern = "*";
- gencache_iterate(print_cache_entry, NULL, pattern);
+ gencache_iterate(print_cache_entry, pattern);
gencache_shutdown();
return 0;
}
@@ -300,7 +280,7 @@ static int net_cache_list(int argc, const char **argv)
static int net_cache_flush(int argc, const char **argv)
{
const char* pattern = "*";
- gencache_iterate(delete_cache_entry, NULL, pattern);
+ gencache_iterate(delete_cache_entry, pattern);
gencache_shutdown();
return 0;
}
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 092d625ae5..d5af6e3fb8 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -1659,10 +1659,6 @@ static int rpc_trustdom_establish(int argc, const char **argv)
domain_name = smb_xstrdup(argv[0]);
strupper(domain_name);
-
- /* account name used at first is our domain's name with '$' */
- asprintf(&acct_name, "%s$", lp_workgroup());
- strupper(acct_name);
/*
* opt_workgroup will be used by connection functions further,
@@ -1673,6 +1669,9 @@ static int rpc_trustdom_establish(int argc, const char **argv)
opt_workgroup = smb_xstrdup(domain_name);
};
+ asprintf(&acct_name, "%s$", lp_workgroup());
+ strupper(acct_name);
+
opt_user_name = acct_name;
/* find the domain controller */
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
deleted file mode 100644
index e710a8c0d0..0000000000
--- a/source3/utils/ntlm_auth.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind status program.
-
- Copyright (C) Tim Potter 2000-2002
- Copyright (C) Andrew Bartlett 2002
- Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000
-
- 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"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_WINBIND
-
-#define SQUID_BUFFER_SIZE 2010
-
-enum squid_mode {
- SQUID_2_5_BASIC,
- SQUID_2_4_BASIC
-};
-
-
-extern int winbindd_fd;
-
-static const char *helper_protocol;
-static const char *username;
-static const char *domain;
-static const char *workstation;
-static const char *hex_challenge;
-static const char *hex_lm_response;
-static const char *hex_nt_response;
-static unsigned char *challenge;
-static size_t challenge_len;
-static unsigned char *lm_response;
-static size_t lm_response_len;
-static unsigned char *nt_response;
-static size_t nt_response_len;
-
-static char *password;
-
-static char winbind_separator(void)
-{
- struct winbindd_response response;
- static BOOL got_sep;
- static char sep;
-
- if (got_sep)
- return sep;
-
- ZERO_STRUCT(response);
-
- /* Send off request */
-
- if (winbindd_request(WINBINDD_INFO, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("could not obtain winbind separator!\n");
- return '\\';
- }
-
- sep = response.data.info.winbind_separator;
- got_sep = True;
-
- if (!sep) {
- d_printf("winbind separator was NULL!\n");
- return '\\';
- }
-
- return sep;
-}
-
-static const char *get_winbind_domain(void)
-{
- struct winbindd_response response;
-
- static fstring winbind_domain;
-
- ZERO_STRUCT(response);
-
- /* Send off request */
-
- if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("could not obtain winbind domain name!\n");
- return NULL;
- }
-
- fstrcpy(winbind_domain, response.data.domain_name);
-
- return winbind_domain;
-
-}
-
-/* Authenticate a user with a plaintext password */
-
-static BOOL check_plaintext_auth(const char *user, const char *pass, BOOL stdout_diagnostics)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- /* Send off request */
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- fstrcpy(request.data.auth.user, user);
- fstrcpy(request.data.auth.pass, pass);
-
- result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response);
-
- /* Display response */
-
- if (stdout_diagnostics) {
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
- d_printf("Reading winbind reply failed! (0x01)\n");
- }
-
- d_printf("%s (0x%x)\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status);
- } else {
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
- DEBUG(1, ("Reading winbind reply failed! (0x01)\n"));
- }
-
- DEBUG(3, ("%s (0x%x)\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status));
- }
-
- return (result == NSS_STATUS_SUCCESS);
-}
-
-static void manage_squid_basic_request(enum squid_mode squid_mode)
-{
- char buf[SQUID_BUFFER_SIZE+1];
- int length;
- char *c, *user, *pass;
- static BOOL err;
-
- if (x_fgets(buf, sizeof(buf)-1, x_stdin) == NULL) {
- DEBUG(1, ("fgets() failed! dying..... errno=%d (%s)\n", errno,
- strerror(errno)));
- exit(1); /* BIIG buffer */
- }
-
- c=memchr(buf,'\n',sizeof(buf)-1);
- if (c) {
- *c = '\0';
- length = c-buf;
- } else {
- err = 1;
- return;
- }
- if (err) {
- DEBUG(2, ("Oversized message\n"));
- x_fprintf(x_stderr, "ERR\n");
- err = 0;
- return;
- }
-
- DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length));
-
- if (buf[0] == '\0') {
- DEBUG(2, ("Invalid Request\n"));
- x_fprintf(x_stderr, "ERR\n");
- return;
- }
-
- user=buf;
-
- pass=memchr(buf,' ',length);
- if (!pass) {
- DEBUG(2, ("Password not found. Denying access\n"));
- x_fprintf(x_stderr, "ERR\n");
- return;
- }
- *pass='\0';
- pass++;
-
- if (squid_mode == SQUID_2_5_BASIC) {
- rfc1738_unescape(user);
- rfc1738_unescape(pass);
- }
-
- if (check_plaintext_auth(user, pass, False)) {
- x_fprintf(x_stdout, "OK\n");
- } else {
- x_fprintf(x_stdout, "ERR\n");
- }
-}
-
-
-static void squid_basic(enum squid_mode squid_mode) {
- /* initialize FDescs */
- x_setbuf(x_stdout, NULL);
- x_setbuf(x_stderr, NULL);
- while(1) {
- manage_squid_basic_request(squid_mode);
- }
-}
-
-
-/* Authenticate a user with a challenge/response */
-
-static BOOL check_auth_crap(void)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
- /* Send off request */
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- fstrcpy(request.data.auth_crap.user, username);
-
- fstrcpy(request.data.auth_crap.domain, domain);
- fstrcpy(request.data.auth_crap.workstation, workstation);
-
- memcpy(request.data.auth_crap.chal, challenge, MIN(challenge_len, 8));
-
- memcpy(request.data.auth_crap.lm_resp, lm_response, MIN(lm_response_len, sizeof(request.data.auth_crap.lm_resp)));
-
- memcpy(request.data.auth_crap.nt_resp, nt_response, MIN(nt_response_len, sizeof(request.data.auth_crap.nt_resp)));
-
- request.data.auth_crap.lm_resp_len = lm_response_len;
- request.data.auth_crap.nt_resp_len = nt_response_len;
-
- result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
-
- /* Display response */
-
- if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) {
- d_printf("Reading winbind reply failed! (0x01)\n");
- }
-
- d_printf("%s (0x%x)\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status);
-
- return result == NSS_STATUS_SUCCESS;
-}
-
-/* Main program */
-
-enum {
- OPT_USERNAME = 1000,
- OPT_DOMAIN,
- OPT_WORKSTATION,
- OPT_CHALLENGE,
- OPT_RESPONSE,
- OPT_LM,
- OPT_NT,
- OPT_PASSWORD
-};
-
-/*************************************************************
- Routine to set hex password characters into an allocated array.
-**************************************************************/
-
-void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
-{
- int i;
- char *hex_buffer;
-
- *out_hex_buffer = smb_xmalloc((len*2)+1);
- hex_buffer = *out_hex_buffer;
-
- for (i = 0; i < len; i++)
- slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
-}
-
-/*************************************************************
- Routine to get the 32 hex characters and turn them
- into a 16 byte array.
-**************************************************************/
-
-BOOL hex_decode(const char *hex_buf_in, unsigned char **out_buffer, size_t *size)
-{
- int i;
- size_t hex_buf_in_len = strlen(hex_buf_in);
- unsigned char partial_byte_hex;
- unsigned char partial_byte;
- char *hexchars = "0123456789ABCDEF";
- char *p;
- BOOL high = True;
-
- if (!hex_buf_in)
- return (False);
-
- *size = (hex_buf_in_len + 1) / 2;
-
- *out_buffer = smb_xmalloc(*size);
-
- for (i = 0; i < hex_buf_in_len; i++) {
- partial_byte_hex = toupper(hex_buf_in[i]);
-
- p = strchr(hexchars, partial_byte_hex);
-
- if (!p)
- return (False);
-
- partial_byte = PTR_DIFF(p, hexchars);
-
- if (high) {
- (*out_buffer)[i / 2] = (partial_byte << 4);
- } else {
- (*out_buffer)[i / 2] |= partial_byte;
- }
- high = !high;
- }
- return (True);
-}
-
-
-int main(int argc, const char **argv)
-{
- int opt;
-
- poptContext pc;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
-
- { "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"},
- { "username", 0, POPT_ARG_STRING, &username, OPT_USERNAME, "username"},
- { "domain", 0, POPT_ARG_STRING, &domain, OPT_DOMAIN, "domain name"},
- { "workstation", 0, POPT_ARG_STRING, &domain, OPT_WORKSTATION, "workstation"},
- { "challenge", 0, POPT_ARG_STRING, &hex_challenge, OPT_CHALLENGE, "challenge (HEX encoded)"},
- { "lm-response", 0, POPT_ARG_STRING, &hex_lm_response, OPT_LM, "LM Response to the challenge (HEX encoded)"},
- { "nt-response", 0, POPT_ARG_STRING, &hex_nt_response, OPT_NT, "NT or NTLMv2 Response to the challenge (HEX encoded)"},
- { "password", 0, POPT_ARG_STRING, &password, OPT_PASSWORD, "User's plaintext password"},
- { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
- { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
- { 0, 0, 0, 0 }
- };
-
- /* Samba client initialisation */
-
- dbf = x_stderr;
-
- /* Parse options */
-
- pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0);
-
- /* Parse command line options */
-
- if (argc == 1) {
- poptPrintHelp(pc, stderr, 0);
- return 1;
- }
-
- pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
- while((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case OPT_CHALLENGE:
- if (!hex_decode(hex_challenge, &challenge, &challenge_len)) {
- fprintf(stderr, "hex decode of %s failed!\n", hex_challenge);
- exit(1);
- }
- break;
- case OPT_LM:
- if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) {
- fprintf(stderr, "hex decode of %s failed!\n", lm_response);
- exit(1);
- }
- break;
- case OPT_NT:
- if (!hex_decode(hex_lm_response, &lm_response, &lm_response_len)) {
- fprintf(stderr, "hex decode of %s failed!\n", lm_response);
- exit(1);
- }
- break;
- }
- }
-
- if (helper_protocol) {
- if (strcmp(helper_protocol, "squid-2.5-basic")== 0) {
- squid_basic(SQUID_2_5_BASIC);
- } else if (strcmp(helper_protocol, "squid-2.4-basic")== 0) {
- squid_basic(SQUID_2_4_BASIC);
- } else {
- fprintf(stderr, "unknown helper protocol [%s]\n", helper_protocol);
- exit(1);
- }
- }
-
- if (domain == NULL) {
- domain = get_winbind_domain();
- }
-
- if (workstation == NULL) {
- workstation = "";
- }
-
- if (challenge) {
- if (!check_auth_crap()) {
- exit(1);
- }
- } else if (password) {
- fstring user;
- snprintf(user, sizeof(user)-1, "%s%c%s", domain, winbind_separator(), username);
- if (!check_plaintext_auth(user, password, True)) {
- exit(1);
- }
- }
-
- /* Exit code */
-
- poptFreeContext(pc);
- return 0;
-}
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index 45a63c4b64..6a019e73d7 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -495,7 +495,7 @@ int main (int argc, char **argv)
poptGetArg(pc); /* Drop argv[0], the program name */
if (user_name == NULL) {
- user_name = poptGetArg(pc);
+ user_name = strdup(poptGetArg(pc));
}
if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
@@ -503,9 +503,6 @@ int main (int argc, char **argv)
exit(1);
}
- if(lp_modules())
- smb_load_modules(lp_modules());
-
if (!init_names())
exit(1);
diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c
deleted file mode 100644
index de18bd0534..0000000000
--- a/source3/utils/profiles.c
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- Samba Unix/Linux SMB client utility profiles.c
- Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/*************************************************************************
-
- A utility to report and change SIDs in registry files
-
- Many of the ideas in here come from other people and software.
- I first looked in Wine in misc/registry.c and was also influenced by
- http://www.wednesday.demon.co.uk/dosreg.html
-
- Which seems to contain comments from someone else. I reproduce them here
- incase the site above disappears. It actually comes from
- http://home.eunet.no/~pnordahl/ntpasswd/WinReg.txt.
-
-The windows NT registry has 2 different blocks, where one can occure many
-times...
-
-the "regf"-Block
-================
-
-"regf" is obviosly the abbreviation for "Registry file". "regf" is the
-signature of the header-block which is always 4kb in size, although only
-the first 64 bytes seem to be used and a checksum is calculated over
-the first 0x200 bytes only!
-
-Offset Size Contents
-0x00000000 D-Word ID: ASCII-"regf" = 0x66676572
-0x00000004 D-Word ???? //see struct REGF
-0x00000008 D-Word ???? Always the same value as at 0x00000004
-0x0000000C Q-Word last modify date in WinNT date-format
-0x00000014 D-Word 1
-0x00000018 D-Word 3
-0x0000001C D-Word 0
-0x00000020 D-Word 1
-0x00000024 D-Word Offset of 1st key record
-0x00000028 D-Word Size of the data-blocks (Filesize-4kb)
-0x0000002C D-Word 1
-0x000001FC D-Word Sum of all D-Words from 0x00000000 to
-0x000001FB //XOR of all words. Nigel
-
-I have analyzed more registry files (from multiple machines running
-NT 4.0 german version) and could not find an explanation for the values
-marked with ???? the rest of the first 4kb page is not important...
-
-the "hbin"-Block
-================
-I don't know what "hbin" stands for, but this block is always a multiple
-of 4kb in size.
-
-Inside these hbin-blocks the different records are placed. The memory-
-management looks like a C-compiler heap management to me...
-
-hbin-Header
-===========
-Offset Size Contents
-0x0000 D-Word ID: ASCII-"hbin" = 0x6E696268
-0x0004 D-Word Offset from the 1st hbin-Block
-0x0008 D-Word Offset to the next hbin-Block
-0x001C D-Word Block-size
-
-The values in 0x0008 and 0x001C should be the same, so I don't know
-if they are correct or swapped...
-
-From offset 0x0020 inside a hbin-block data is stored with the following
-format:
-
-Offset Size Contents
-0x0000 D-Word Data-block size //this size must be a
-multiple of 8. Nigel
-0x0004 ???? Data
-
-If the size field is negative (bit 31 set), the corresponding block
-is free and has a size of -blocksize!
-
-The data is stored as one record per block. Block size is a multiple
-of 4 and the last block reaches the next hbin-block, leaving no room.
-
-Records in the hbin-blocks
-==========================
-
-nk-Record
-
- The nk-record can be treated as a kombination of tree-record and
- key-record of the win 95 registry.
-
-lf-Record
-
- The lf-record is the counterpart to the RGKN-record (the
- hash-function)
-
-vk-Record
-
- The vk-record consists information to a single value.
-
-sk-Record
-
- sk (? Security Key ?) is the ACL of the registry.
-
-Value-Lists
-
- The value-lists contain information about which values are inside a
- sub-key and don't have a header.
-
-Datas
-
- The datas of the registry are (like the value-list) stored without a
- header.
-
-All offset-values are relative to the first hbin-block and point to the
-block-size field of the record-entry. to get the file offset, you have to add
-the header size (4kb) and the size field (4 bytes)...
-
-the nk-Record
-=============
-Offset Size Contents
-0x0000 Word ID: ASCII-"nk" = 0x6B6E
-0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel
-0x0004 Q-Word write-date/time in windows nt notation
-0x0010 D-Word Offset of Owner/Parent key
-0x0014 D-Word number of sub-Keys
-0x001C D-Word Offset of the sub-key lf-Records
-0x0024 D-Word number of values
-0x0028 D-Word Offset of the Value-List
-0x002C D-Word Offset of the sk-Record
-
-0x0030 D-Word Offset of the Class-Name //see NK structure for the use of these fields. Nigel
-0x0044 D-Word Unused (data-trash) //some kind of run time index. Does not appear to be important. Nigel
-0x0048 Word name-length
-0x004A Word class-name length
-0x004C ???? key-name
-
-the Value-List
-==============
-Offset Size Contents
-0x0000 D-Word Offset 1st Value
-0x0004 D-Word Offset 2nd Value
-0x???? D-Word Offset nth Value
-
-To determine the number of values, you have to look at the owner-nk-record!
-
-Der vk-Record
-=============
-Offset Size Contents
-0x0000 Word ID: ASCII-"vk" = 0x6B76
-0x0002 Word name length
-0x0004 D-Word length of the data //if top bit is set when offset contains data. Nigel
-0x0008 D-Word Offset of Data
-0x000C D-Word Type of value
-0x0010 Word Flag
-0x0012 Word Unused (data-trash)
-0x0014 ???? Name
-
-If bit 0 of the flag-word is set, a name is present, otherwise the value has no name (=default)
-
-If the data-size is lower 5, the data-offset value is used to store the data itself!
-
-The data-types
-==============
-Wert Beteutung
-0x0001 RegSZ: character string (in UNICODE!)
-0x0002 ExpandSZ: string with "%var%" expanding (UNICODE!)
-0x0003 RegBin: raw-binary value
-0x0004 RegDWord: Dword
-0x0007 RegMultiSZ: multiple strings, separated with 0
- (UNICODE!)
-
-The "lf"-record
-===============
-Offset Size Contents
-0x0000 Word ID: ASCII-"lf" = 0x666C
-0x0002 Word number of keys
-0x0004 ???? Hash-Records
-
-Hash-Record
-===========
-Offset Size Contents
-0x0000 D-Word Offset of corresponding "nk"-Record
-0x0004 D-Word ASCII: the first 4 characters of the key-name, padded with 0's. Case sensitiv!
-
-Keep in mind, that the value at 0x0004 is used for checking the data-consistency! If you change the
-key-name you have to change the hash-value too!
-
-//These hashrecords must be sorted low to high within the lf record. Nigel.
-
-The "sk"-block
-==============
-(due to the complexity of the SAM-info, not clear jet)
-
-Offset Size Contents
-0x0000 Word ID: ASCII-"sk" = 0x6B73
-0x0002 Word Unused
-0x0004 D-Word Offset of previous "sk"-Record
-0x0008 D-Word Offset of next "sk"-Record
-0x000C D-Word usage-counter
-0x0010 D-Word Size of "sk"-record in bytes
-???? //standard self
-relative security desciptor. Nigel
-???? ???? Security and auditing settings...
-????
-
-The usage counter counts the number of references to this
-"sk"-record. You can use one "sk"-record for the entire registry!
-
-Windows nt date/time format
-===========================
-The time-format is a 64-bit integer which is incremented every
-0,0000001 seconds by 1 (I don't know how accurate it realy is!)
-It starts with 0 at the 1st of january 1601 0:00! All values are
-stored in GMT time! The time-zone is important to get the real
-time!
-
-Common values for win95 and win-nt
-==================================
-Offset values marking an "end of list", are either 0 or -1 (0xFFFFFFFF).
-If a value has no name (length=0, flag(bit 0)=0), it is treated as the
-"Default" entry...
-If a value has no data (length=0), it is displayed as empty.
-
-simplyfied win-3.?? registry:
-=============================
-
-+-----------+
-| next rec. |---+ +----->+------------+
-| first sub | | | | Usage cnt. |
-| name | | +-->+------------+ | | length |
-| value | | | | next rec. | | | text |------->+-------+
-+-----------+ | | | name rec. |--+ +------------+ | xxxxx |
- +------------+ | | value rec. |-------->+------------+ +-------+
- v | +------------+ | Usage cnt. |
-+-----------+ | | length |
-| next rec. | | | text |------->+-------+
-| first sub |------+ +------------+ | xxxxx |
-| name | +-------+
-| value |
-+-----------+
-
-Greatly simplyfied structure of the nt-registry:
-================================================
-
-+---------------------------------------------------------------+
-| |
-v |
-+---------+ +---------->+-----------+ +----->+---------+ |
-| "nk" | | | lf-rec. | | | nk-rec. | |
-| ID | | | # of keys | | | parent |---+
-| Date | | | 1st key |--+ | .... |
-| parent | | +-----------+ +---------+
-| suk-keys|-----+
-| values |--------------------->+----------+
-| SK-rec. |---------------+ | 1. value |--> +----------+
-| class |--+ | +----------+ | vk-rec. |
-+---------+ | | | .... |
- v | | data |--> +-------+
- +------------+ | +----------+ | xxxxx |
- | Class name | | +-------+
- +------------+ |
- v
- +---------+ +---------+
- +----->| next sk |--->| Next sk |--+
- | +---| prev sk |<---| prev sk | |
- | | | .... | | ... | |
- | | +---------+ +---------+ |
- | | ^ | |
- | +----------+ |
- +-------------------------------+
-
----------------------------------------------------------------------------
-
-Hope this helps.... (Although it was "fun" for me to uncover this things,
- it took me several sleepless nights ;)
-
- B.D.
-
-*************************************************************************/
-#include "includes.h"
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-typedef unsigned int DWORD;
-typedef unsigned short WORD;
-
-#define REG_REGF_ID 0x66676572
-
-typedef struct regf_block {
- DWORD REGF_ID; /* regf */
- DWORD uk1;
- DWORD uk2;
- DWORD tim1, tim2;
- DWORD uk3; /* 1 */
- DWORD uk4; /* 3 */
- DWORD uk5; /* 0 */
- DWORD uk6; /* 1 */
- DWORD first_key; /* offset */
- unsigned int dblk_size;
- DWORD uk7[116]; /* 1 */
- DWORD chksum;
-} REGF_HDR;
-
-typedef struct hbin_sub_struct {
- DWORD dblocksize;
- char data[1];
-} HBIN_SUB_HDR;
-
-#define REG_HBIN_ID 0x6E696268
-
-typedef struct hbin_struct {
- DWORD HBIN_ID; /* hbin */
- DWORD next_off;
- DWORD prev_off;
- DWORD uk1;
- DWORD uk2;
- DWORD uk3;
- DWORD uk4;
- DWORD blk_size;
- HBIN_SUB_HDR hbin_sub_hdr;
-} HBIN_HDR;
-
-#define REG_NK_ID 0x6B6E
-
-typedef struct nk_struct {
- WORD NK_ID;
- WORD type;
- DWORD t1, t2;
- DWORD uk1;
- DWORD own_off;
- DWORD subk_num;
- DWORD uk2;
- DWORD lf_off;
- DWORD uk3;
- DWORD val_cnt;
- DWORD val_off;
- DWORD sk_off;
- DWORD clsnam_off;
-} NK_HDR;
-
-#define REG_SK_ID 0x6B73
-
-typedef struct sk_struct {
- WORD SK_ID;
- WORD uk1;
- DWORD prev_off;
- DWORD next_off;
- DWORD ref_cnt;
- DWORD rec_size;
- char sec_desc[1];
-} SK_HDR;
-
-typedef struct sec_desc_rec {
- WORD rev;
- WORD type;
- DWORD owner_off;
- DWORD group_off;
- DWORD sacl_off;
- DWORD dacl_off;
-} MY_SEC_DESC;
-
-typedef struct ace_struct {
- unsigned char type;
- unsigned char flags;
- unsigned short length;
- unsigned int perms;
- DOM_SID trustee;
-} ACE;
-
-typedef struct acl_struct {
- WORD rev;
- WORD size;
- DWORD num_aces;
- ACE *aces; /* One or more ACEs */
-} ACL;
-
-#define OFF(f) (0x1000 + (f) + 4)
-
-void print_sid(DOM_SID *sid);
-
-int verbose = 1;
-DOM_SID old_sid, new_sid;
-int change = 0, new = 0;
-
-/* Compare two SIDs for equality */
-int my_sid_equal(DOM_SID *s1, DOM_SID *s2)
-{
- int sa1, sa2;
-
- if (s1->sid_rev_num != s2->sid_rev_num) return 0;
-
- sa1 = s1->num_auths; sa2 = s2->num_auths;
-
- if (sa1 != sa2) return 0;
-
- return !bcmp((char *)&s1->id_auth, (char *)&s2->id_auth,
- 6 + sa1 * 4);
-
-}
-
-/*
- * Quick and dirty to read a SID in S-1-5-21-x-y-z-rid format and
- * construct a DOM_SID
- */
-int get_sid(DOM_SID *sid, char *sid_str)
-{
- int i = 0, auth;
- char *lstr;
-
- if (strncmp(sid_str, "S-1-5", 5)) {
- fprintf(stderr, "Does not conform to S-1-5...: %s\n", sid_str);
- return 0;
- }
-
- /* We only allow strings of form S-1-5... */
-
- sid->sid_rev_num = 1;
- sid->id_auth[5] = 5;
-
- lstr = sid_str + 5;
-
- while (1) {
- if (!lstr || !lstr[0] || sscanf(lstr, "-%u", &auth) == 0) {
- if (i < 4) {
- fprintf(stderr, "Not of form -d-d...: %s, %u\n", lstr, i);
- return 0;
- }
- sid->num_auths=i;
- print_sid(sid);
- return 1;
- }
-
- SIVAL(&sid->sub_auths[i], 0, auth);
- i++;
- lstr = strchr(lstr + 1, '-');
- }
-
- return 1;
-}
-
-/*
- * Replace SID1, component by component with SID2
- * Assumes will never be called with unequal length SIDS
- * so only touches 21-x-y-z-rid portion
- * This routine does not need to deal with endianism as
- * long as the incoming SIDs are both in the same (LE) format.
- */
-void change_sid(DOM_SID *s1, DOM_SID *s2)
-{
- int i;
-
- for (i=0; i<s1->num_auths; i++) {
- s1->sub_auths[i] = s2->sub_auths[i];
- }
-}
-
-void print_sid(DOM_SID *sid)
-{
- int i, comps = sid->num_auths;
- fprintf(stdout, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
-
- for (i = 0; i < comps; i++) {
-
- fprintf(stdout, "-%u", IVAL(&sid->sub_auths[i],0));
-
- }
- fprintf(stdout, "\n");
-}
-
-void process_sid(DOM_SID *sid, DOM_SID *o_sid, DOM_SID *n_sid)
-{
- int i;
- if (my_sid_equal(sid, o_sid)) {
-
- for (i=0; i<sid->num_auths; i++) {
- sid->sub_auths[i] = n_sid->sub_auths[i];
-
- }
-
- }
-
-}
-
-void process_acl(ACL *acl, char *prefix)
-{
- int ace_cnt, i;
- ACE *ace;
-
- ace_cnt = IVAL(&acl->num_aces, 0);
- ace = (ACE *)&acl->aces;
- if (verbose) fprintf(stdout, "%sACEs: %u\n", prefix, ace_cnt);
- for (i=0; i<ace_cnt; i++) {
- if (verbose) fprintf(stdout, "%s Perms: %08X, SID: ", prefix,
- IVAL(&ace->perms, 0));
- if (change)
- process_sid(&ace->trustee, &old_sid, &new_sid);
- print_sid(&ace->trustee);
- ace = (ACE *)((char *)ace + SVAL(&ace->length, 0));
- }
-}
-
-void usage(void)
-{
- fprintf(stderr, "usage: profiles [-c <OLD-SID> -n <NEW-SID>] <profilefile>\n");
- fprintf(stderr, "Version: %s\n", VERSION);
- fprintf(stderr, "\n\t-v\t sets verbose mode");
- fprintf(stderr, "\n\t-c S-1-5-21-z-y-x-oldrid - provides SID to change");
- fprintf(stderr, "\n\t-n S-1-5-21-a-b-c-newrid - provides SID to change to");
- fprintf(stderr, "\n\t\tBoth must be present if the other is.");
- fprintf(stderr, "\n\t\tIf neither present, just report the SIDs found\n");
-}
-
-int main(int argc, char *argv[])
-{
- extern char *optarg;
- extern int optind;
- int opt;
- int fd, start = 0;
- char *base;
- struct stat sbuf;
- REGF_HDR *regf_hdr;
- HBIN_HDR *hbin_hdr;
- NK_HDR *nk_hdr;
- SK_HDR *sk_hdr;
- WORD first_sk_off, sk_off;
- MY_SEC_DESC *sec_desc;
- int *ptr;
-
- if (argc < 2) {
- usage();
- exit(1);
- }
-
- /*
- * Now, process the arguments
- */
-
- while ((opt = getopt(argc, argv, "c:n:v")) != EOF) {
- switch (opt) {
- case 'c':
- change = 1;
- if (!get_sid(&old_sid, optarg)) {
- fprintf(stderr, "Argument to -c should be a SID in form of S-1-5-...\n");
- usage();
- exit(254);
- }
- break;
-
- case 'n':
- new = 1;
- if (!get_sid(&new_sid, optarg)) {
- fprintf(stderr, "Argument to -n should be a SID in form of S-1-5-...\n");
- usage();
- exit(253);
- }
-
- break;
-
- case 'v':
- verbose++;
- break;
-
- default:
- usage();
- exit(255);
- }
- }
-
- if ((!change & new) || (change & !new)) {
- fprintf(stderr, "You must specify both -c and -n if one or the other is set!\n");
- usage();
- exit(252);
- }
-
- fd = open(argv[optind], O_RDWR, 0000);
-
- if (fd < 0) {
- fprintf(stderr, "Could not open %s: %s\n", argv[optind],
- strerror(errno));
- exit(2);
- }
-
- if (fstat(fd, &sbuf) < 0) {
- fprintf(stderr, "Could not stat file %s, %s\n", argv[optind],
- strerror(errno));
- exit(3);
- }
-
- /*
- * Now, mmap the file into memory, check the header and start
- * dealing with the records. We are interested in the sk record
- */
- start = 0;
- base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-
- if ((int)base == -1) {
- fprintf(stderr, "Could not mmap file: %s, %s\n", argv[optind],
- strerror(errno));
- exit(4);
- }
-
- /*
- * In what follows, and in places above, in order to work on both LE and
- * BE platforms, we have to use the Samba macros to extract SHORT, LONG
- * and associated UNSIGNED quantities from the data in the mmap'd file.
- * NOTE, however, that we do not need to do anything with memory
- * addresses that we construct from pointers in our address space.
- * For example,
- *
- * sec_desc = (MY_SEC_DESC *)&(sk_hdr->sec_desc[0]);
- *
- * is simply taking the address of a structure we already have the address
- * of in our address space, while, the fields within it, will have to
- * be accessed with the macros:
- *
- * owner_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] +
- * IVAL(&sec_desc->owner_off, 0));
- *
- * Which is pulling out an offset and adding it to an existing pointer.
- *
- */
-
- regf_hdr = (REGF_HDR *)base;
-
- if (verbose) fprintf(stdout, "Registry file size: %u\n", (unsigned int)sbuf.st_size);
-
- if (IVAL(&regf_hdr->REGF_ID, 0) != REG_REGF_ID) {
- fprintf(stderr, "Incorrect Registry file (doesn't have header ID): %s\n", argv[optind]);
- exit(5);
- }
-
- if (verbose) fprintf(stdout, "First Key Off: %u, Data Block Size: %u\n",
- IVAL(&regf_hdr->first_key, 0),
- IVAL(&regf_hdr->dblk_size, 0));
-
- hbin_hdr = (HBIN_HDR *)(base + 0x1000); /* No need for Endian stuff */
-
- /*
- * This should be the hbin_hdr
- */
-
- if (IVAL(&hbin_hdr->HBIN_ID, 0) != REG_HBIN_ID) {
- fprintf(stderr, "Incorrect hbin hdr: %s\n", argv[optind]);
- exit(6);
- }
-
- if (verbose) fprintf(stdout, "Next Off: %u, Prev Off: %u\n",
- IVAL(&hbin_hdr->next_off, 0),
- IVAL(&hbin_hdr->prev_off, 0));
-
- nk_hdr = (NK_HDR *)(base + 0x1000 + IVAL(&regf_hdr->first_key, 0) + 4);
-
- if (SVAL(&nk_hdr->NK_ID, 0) != REG_NK_ID) {
- fprintf(stderr, "Incorrect NK Header: %s\n", argv[optind]);
- exit(7);
- }
-
- sk_off = first_sk_off = IVAL(&nk_hdr->sk_off, 0);
- if (verbose) {
- fprintf(stdout, "Type: %0x\n", SVAL(&nk_hdr->type, 0));
- fprintf(stdout, "SK Off : %o\n", (0x1000 + sk_off + 4));
- }
-
- sk_hdr = (SK_HDR *)(base + 0x1000 + sk_off + 4);
-
- do {
- DOM_SID *owner_sid, *group_sid;
- ACL *sacl, *dacl;
- if (SVAL(&sk_hdr->SK_ID, 0) != REG_SK_ID) {
- fprintf(stderr, "Incorrect SK Header format: %08X\n",
- (0x1000 + sk_off + 4));
- exit(8);
- }
- ptr = (int *)sk_hdr;
- if (verbose) fprintf(stdout, "Off: %08X, Refs: %u, Size: %u\n",
- sk_off, IVAL(&sk_hdr->ref_cnt, 0),
- IVAL(&sk_hdr->rec_size, 0));
-
- sec_desc = (MY_SEC_DESC *)&(sk_hdr->sec_desc[0]);
- owner_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] +
- IVAL(&sec_desc->owner_off, 0));
- group_sid = (DOM_SID *)(&sk_hdr->sec_desc[0] +
- IVAL(&sec_desc->group_off, 0));
- sacl = (ACL *)(&sk_hdr->sec_desc[0] +
- IVAL(&sec_desc->sacl_off, 0));
- dacl = (ACL *)(&sk_hdr->sec_desc[0] +
- IVAL(&sec_desc->dacl_off, 0));
- if (verbose)fprintf(stdout, " Owner SID: ");
- if (change) process_sid(owner_sid, &old_sid, &new_sid);
- if (verbose) print_sid(owner_sid);
- if (verbose) fprintf(stdout, " Group SID: ");
- if (change) process_sid(group_sid, &old_sid, &new_sid);
- if (verbose) print_sid(group_sid);
- fprintf(stdout, " SACL: ");
- if (!sec_desc->sacl_off) { /* LE zero == BE zero */
- if (verbose) fprintf(stdout, "NONE\n");
- }
- else
- process_acl(sacl, " ");
- if (verbose) fprintf(stdout, " DACL: ");
- if (!sec_desc->dacl_off) {
- if (verbose) fprintf(stdout, "NONE\n");
- }
- else
- process_acl(dacl, " ");
- sk_off = IVAL(&sk_hdr->prev_off, 0);
- sk_hdr = (SK_HDR *)(base + OFF(IVAL(&sk_hdr->prev_off, 0)));
- } while (sk_off != first_sk_off);
-
- munmap(base, sbuf.st_size);
-
- close(fd);
- return 0;
-}
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index 933cabdb4b..2f3bb2e0da 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -470,7 +470,7 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
JOB_STATUS_DELETED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
}
-
+
/* printer change notify */
if (strequal(cmd, "printer")) {
diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c
index 1a0d639f02..5a2d394706 100644
--- a/source3/utils/smbfilter.c
+++ b/source3/utils/smbfilter.c
@@ -19,6 +19,7 @@
*/
#include "includes.h"
+#include "smb.h"
#define SECURITY_MASK 0
#define SECURITY_SET 0
diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
index 95c4b2b265..d30bd916b2 100644
--- a/source3/utils/testparm.c
+++ b/source3/utils/testparm.c
@@ -33,6 +33,7 @@
*/
#include "includes.h"
+#include "smb.h"
extern BOOL AllowDebugChange;
diff --git a/source3/utils/testprns.c b/source3/utils/testprns.c
index 1c13bb4ce3..66c8e9bfd6 100644
--- a/source3/utils/testprns.c
+++ b/source3/utils/testprns.c
@@ -31,6 +31,7 @@
*/
#include "includes.h"
+#include "smb.h"
int main(int argc, char *argv[])
{