diff options
107 files changed, 1 insertions, 48153 deletions
diff --git a/source4/include/includes.h b/source4/include/includes.h index f9598845c3..bc3d948a2c 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -723,8 +723,6 @@ extern int errno; #include "mangle.h" -#include "nsswitch/winbind_client.h" - #include "mutex.h" #include "librpc/rpc/dcerpc.h" @@ -750,8 +748,6 @@ struct functable { typedef int (*comparison_fn_t)(const void *, const void *); #endif -#include "nsswitch/nss.h" - /***** automatically generated prototypes *****/ #include "proto.h" diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 78acb5bb1c..55254498d9 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -43,8 +43,6 @@ ADD_OBJ_FILES = \ lib/tallocmsg.o \ lib/dmallocmsg.o \ lib/smbpasswd.o \ - nsswitch/wb_client.o \ - nsswitch/wb_common.o \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/account_pol.o \ diff --git a/source4/lib/username.c b/source4/lib/username.c index 3af9dbd027..2d9d212858 100644 --- a/source4/lib/username.c +++ b/source4/lib/username.c @@ -169,82 +169,6 @@ struct passwd *Get_Pwnam(const char *user) } /**************************************************************************** - Check if a user is in a winbind group. -****************************************************************************/ - -static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered) -{ - int num_groups; - int i; - gid_t *groups = NULL; - gid_t gid, gid_low, gid_high; - BOOL ret = False; - - *winbind_answered = False; - - if ((gid = nametogid(gname)) == (gid_t)-1) { - DEBUG(0,("user_in_winbind_group_list: nametogid for group %s failed.\n", - gname )); - goto err; - } - - if (!lp_winbind_gid(&gid_low, &gid_high)) { - DEBUG(4, ("winbind gid range not configured, therefore %s cannot be a winbind group\n", gname)); - goto err; - } - - if (gid < gid_low || gid > gid_high) { - DEBUG(4, ("group %s is not a winbind group\n", gname)); - goto err; - } - - /* - * Get the gid's that this user belongs to. - */ - - if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) - return False; - - if (num_groups == 0) { - *winbind_answered = True; - return False; - } - - if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { - DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); - goto err; - } - - if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { - DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ -failed with error %s\n", strerror(errno) )); - goto err; - } - - /* - * Now we have the gid list for this user - convert the gname - * to a gid_t via either winbind or the local UNIX lookup and do the comparison. - */ - - for (i = 0; i < num_groups; i++) { - if (gid == groups[i]) { - ret = True; - break; - } - } - - *winbind_answered = True; - SAFE_FREE(groups); - return ret; - - err: - - *winbind_answered = False; - SAFE_FREE(groups); - return False; -} - -/**************************************************************************** Check if a user is in a UNIX group. ****************************************************************************/ static BOOL user_in_unix_group_list(const char *user,const char *gname) @@ -298,7 +222,6 @@ exit: ****************************************************************************/ static BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups, size_t n_groups) { - BOOL winbind_answered = False; BOOL ret; gid_t gid; unsigned i; @@ -317,11 +240,7 @@ static BOOL user_in_group_list(const char *user, const char *gname, gid_t *group } /* fallback if we don't yet have the group list */ - - ret = user_in_winbind_group_list(user, gname, &winbind_answered); - if (!winbind_answered) - ret = user_in_unix_group_list(user, gname); - + ret = user_in_unix_group_list(user, gname); if (ret) DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n", user, gname)); return ret; diff --git a/source4/modules/developer.c b/source4/modules/developer.c deleted file mode 100644 index a697abcd22..0000000000 --- a/source4/modules/developer.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba module with developer tools - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jelmer Vernooij 2002 - - 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" - -static struct { - char from; - char *to; - int len; -} weird_table[] = { - {'q', "^q^", 3}, - {'Q', "^Q^", 3}, - {0, NULL} -}; - -static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - int i; - int done = 0; - for (i=0;weird_table[i].from;i++) { - if (strncmp((*inbuf), - weird_table[i].to, - weird_table[i].len) == 0) { - if (*inbytesleft < weird_table[i].len) { - DEBUG(0,("ERROR: truncated weird string\n")); - /* smb_panic("weird_pull"); */ - - } else { - (*outbuf)[0] = weird_table[i].from; - (*outbuf)[1] = 0; - (*inbytesleft) -= weird_table[i].len; - (*outbytesleft) -= 2; - (*inbuf) += weird_table[i].len; - (*outbuf) += 2; - done = 1; - break; - } - } - } - if (done) continue; - (*outbuf)[0] = (*inbuf)[0]; - (*outbuf)[1] = 0; - (*inbytesleft) -= 1; - (*outbytesleft) -= 2; - (*inbuf) += 1; - (*outbuf) += 2; - } - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int ir_count=0; - - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - int i; - int done=0; - for (i=0;weird_table[i].from;i++) { - if ((*inbuf)[0] == weird_table[i].from && - (*inbuf)[1] == 0) { - if (*outbytesleft < weird_table[i].len) { - DEBUG(0,("No room for weird character\n")); - /* smb_panic("weird_push"); */ - } else { - memcpy(*outbuf, weird_table[i].to, - weird_table[i].len); - (*inbytesleft) -= 2; - (*outbytesleft) -= weird_table[i].len; - (*inbuf) += 2; - (*outbuf) += weird_table[i].len; - done = 1; - break; - } - } - } - if (done) continue; - - (*outbuf)[0] = (*inbuf)[0]; - if ((*inbuf)[1]) ir_count++; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return ir_count; -} - -struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push}; - -int init_module(void) -{ - smb_register_charset(&weird_functions); - return 1; -} diff --git a/source4/modules/mysql.c b/source4/modules/mysql.c deleted file mode 100644 index 1d5819295b..0000000000 --- a/source4/modules/mysql.c +++ /dev/null @@ -1,1043 +0,0 @@ - -/* - * MySQL password backend for samba - * Copyright (C) Jelmer Vernooij 2002 - * - * 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 <mysql/mysql.h> - -#define CONFIG_TABLE_DEFAULT "user" -#define CONFIG_LOGON_TIME_DEFAULT "logon_time" -#define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time" -#define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time" -#define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time" -#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time" -#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time" -#define CONFIG_USERNAME_DEFAULT "username" -#define CONFIG_DOMAIN_DEFAULT "domain" -#define CONFIG_NT_USERNAME_DEFAULT "nt_username" -#define CONFIG_FULLNAME_DEFAULT "nt_fullname" -#define CONFIG_HOME_DIR_DEFAULT "home_dir" -#define CONFIG_DIR_DRIVE_DEFAULT "dir_drive" -#define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script" -#define CONFIG_PROFILE_PATH_DEFAULT "profile_path" -#define CONFIG_ACCT_DESC_DEFAULT "acct_desc" -#define CONFIG_WORKSTATIONS_DEFAULT "workstations" -#define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str" -#define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial" -#define CONFIG_UID_DEFAULT "uid" -#define CONFIG_GID_DEFAULT "gid" -#define CONFIG_USER_SID_DEFAULT "user_sid" -#define CONFIG_GROUP_SID_DEFAULT "group_sid" -#define CONFIG_LM_PW_DEFAULT "lm_pw" -#define CONFIG_NT_PW_DEFAULT "nt_pw" -#define CONFIG_PLAIN_PW_DEFAULT "NULL" -#define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl" -#define CONFIG_UNKNOWN_3_DEFAULT "unknown_3" -#define CONFIG_LOGON_DIVS_DEFAULT "logon_divs" -#define CONFIG_HOURS_LEN_DEFAULT "hours_len" -#define CONFIG_UNKNOWN_5_DEFAULT "unknown_5" -#define CONFIG_UNKNOWN_6_DEFAULT "unknown_6" -#define CONFIG_HOST_DEFAULT "localhost" -#define CONFIG_USER_DEFAULT "samba" -#define CONFIG_PASS_DEFAULT "" -#define CONFIG_PORT_DEFAULT "3306" -#define CONFIG_DB_DEFAULT "samba" - -static int mysqlsam_debug_level = DBGC_ALL; - -#undef DBGC_CLASS -#define DBGC_CLASS mysqlsam_debug_level - -typedef struct pdb_mysql_data { - MYSQL *handle; - MYSQL_RES *pwent; - const char *location; -} pdb_mysql_data; - -/* Used to construct insert and update queries */ - -typedef struct pdb_mysql_query { - char update; - TALLOC_CTX *mem_ctx; - char *part1; - char *part2; -} pdb_mysql_query; -#define SET_DATA(data,methods) { \ - if(!methods){ \ - DEBUG(0, ("invalid methods!\n")); \ - return NT_STATUS_INVALID_PARAMETER; \ - } \ - data = (struct pdb_mysql_data *)methods->private_data; \ - if(!data || !(data->handle)){ \ - DEBUG(0, ("invalid handle!\n")); \ - return NT_STATUS_INVALID_HANDLE; \ - } \ -} - -static void pdb_mysql_int_field(struct pdb_methods *m, - struct pdb_mysql_query *q, char *name, int value) -{ - if (!name || strchr(name, '\'')) - return; /* This field shouldn't be set by us */ - - if (q->update) { - q->part1 = - talloc_asprintf_append(q->mem_ctx, q->part1, - "%s = %d,", name, value); - } else { - q->part1 = - talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name); - q->part2 = - talloc_asprintf_append(q->mem_ctx, q->part2, "%d,", value); - } -} - -static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods, - struct pdb_mysql_query *q, - char *name, const char *value) -{ - char *esc_value; - struct pdb_mysql_data *data; - char *tmp_value; - - SET_DATA(data, methods); - - if (!name || !value || !strcmp(value, "") || strchr(name, '\'')) - return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */ - - esc_value = malloc(strlen(value) * 2 + 1); - - tmp_value = smb_xstrdup(value); - mysql_real_escape_string(data->handle, esc_value, tmp_value, - strlen(tmp_value)); - SAFE_FREE(tmp_value); - - if (q->update) { - q->part1 = - talloc_asprintf_append(q->mem_ctx, q->part1, - "%s = '%s',", name, esc_value); - } else { - q->part1 = - talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name); - q->part2 = - talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',", - esc_value); - } - - SAFE_FREE(esc_value); - - return NT_STATUS_OK; -} - -static char * config_value(pdb_mysql_data * data, char *name, char *default_value) -{ - if (lp_parm_string(NULL, data->location, name)) - return lp_parm_string(NULL, data->location, name); - - return default_value; -} - -static char * config_value_write(pdb_mysql_data * data, char *name, char *default_value) { - char *v = config_value(data, name, NULL); - char *swrite; - - if (!v) - return default_value; - - swrite = strchr(v, ':'); - - /* Default to the same field as read field */ - if (!swrite) - return v; - - swrite++; - - /* If the field is 0 chars long, we shouldn't write to it */ - if (!strlen(swrite) || !strcmp(swrite, "NULL")) - return NULL; - - /* Otherwise, use the additionally specified */ - return swrite; -} - -static const char * config_value_read(pdb_mysql_data * data, char *name, char *default_value) -{ - char *v = config_value(data, name, NULL); - char *swrite; - - if (!v) - return default_value; - - swrite = strchr(v, ':'); - - /* If no write is specified, there are no problems */ - if (!swrite) { - if (strlen(v) == 0) - return "NULL"; - return v; - } - - /* Otherwise, we have to cut the ':write_part' */ - *swrite = '\0'; - if (strlen(v) == 0) - return "NULL"; - - return v; -} - -/* Wrapper for atol that returns 0 if 'a' points to NULL */ -static long xatol(char *a) -{ - long ret = 0; - - if (a != NULL) - ret = atol(a); - - return ret; -} - -static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u) -{ - MYSQL_ROW row; - pstring temp; - unsigned int num_fields; - DOM_SID sid; - - num_fields = mysql_num_fields(r); - row = mysql_fetch_row(r); - if (!row) - return NT_STATUS_INVALID_PARAMETER; - - pdb_set_logon_time(u, xatol(row[0]), PDB_SET); - pdb_set_logoff_time(u, xatol(row[1]), PDB_SET); - pdb_set_kickoff_time(u, xatol(row[2]), PDB_SET); - pdb_set_pass_last_set_time(u, xatol(row[3]), PDB_SET); - pdb_set_pass_can_change_time(u, xatol(row[4]), PDB_SET); - pdb_set_pass_must_change_time(u, xatol(row[5]), PDB_SET); - pdb_set_username(u, row[6], PDB_SET); - pdb_set_domain(u, row[7], PDB_SET); - pdb_set_nt_username(u, row[8], PDB_SET); - pdb_set_fullname(u, row[9], PDB_SET); - pdb_set_homedir(u, row[10], PDB_SET); - pdb_set_dir_drive(u, row[11], PDB_SET); - pdb_set_logon_script(u, row[12], PDB_SET); - pdb_set_profile_path(u, row[13], PDB_SET); - pdb_set_acct_desc(u, row[14], PDB_SET); - pdb_set_workstations(u, row[15], PDB_SET); - pdb_set_unknown_str(u, row[16], PDB_SET); - pdb_set_munged_dial(u, row[17], PDB_SET); - - if (row[18]) - pdb_set_uid(u, xatol(row[18]), PDB_SET); - if (row[19]) - pdb_set_gid(u, xatol(row[19]), PDB_SET); - - string_to_sid(&sid, row[20]); - pdb_set_user_sid(u, &sid, PDB_SET); - string_to_sid(&sid, row[21]); - pdb_set_group_sid(u, &sid, PDB_SET); - - if (pdb_gethexpwd(row[22], temp), PDB_SET) - pdb_set_lanman_passwd(u, temp, PDB_SET); - if (pdb_gethexpwd(row[23], temp), PDB_SET) - pdb_set_nt_passwd(u, temp, PDB_SET); - - /* Only use plaintext password storage when lanman and nt are - * NOT used */ - if (!row[22] || !row[23]) - pdb_set_plaintext_passwd(u, row[24]); - - pdb_set_acct_ctrl(u, xatol(row[25]), PDB_SET); - pdb_set_unknown_3(u, xatol(row[26]), PDB_SET); - pdb_set_logon_divs(u, xatol(row[27]), PDB_SET); - pdb_set_hours_len(u, xatol(row[28]), PDB_SET); - pdb_set_unknown_5(u, xatol(row[29]), PDB_SET); - pdb_set_unknown_6(u, xatol(row[30]), PDB_SET); - - return NT_STATUS_OK; -} - -static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update) -{ - struct pdb_mysql_data *data = - (struct pdb_mysql_data *) methods->private_data; - char *query; - int ret; - - if (!data || !(data->handle)) { - DEBUG(0, ("invalid handle!\n")); - return NT_STATUS_INVALID_HANDLE; - } - - asprintf(&query, - "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s", - config_value_read(data, "logon time column", - CONFIG_LOGON_TIME_DEFAULT), - config_value_read(data, "logoff time column", - CONFIG_LOGOFF_TIME_DEFAULT), - config_value_read(data, "kickoff time column", - CONFIG_KICKOFF_TIME_DEFAULT), - config_value_read(data, "pass last set time column", - CONFIG_PASS_LAST_SET_TIME_DEFAULT), - config_value_read(data, "pass can change time column", - CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT), - config_value_read(data, "pass must change time column", - CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT), - config_value_read(data, "username column", - CONFIG_USERNAME_DEFAULT), - config_value_read(data, "domain column", - CONFIG_DOMAIN_DEFAULT), - config_value_read(data, "nt username column", - CONFIG_NT_USERNAME_DEFAULT), - config_value_read(data, "fullname column", - CONFIG_FULLNAME_DEFAULT), - config_value_read(data, "home dir column", - CONFIG_HOME_DIR_DEFAULT), - config_value_read(data, "dir drive column", - CONFIG_DIR_DRIVE_DEFAULT), - config_value_read(data, "logon script column", - CONFIG_LOGON_SCRIPT_DEFAULT), - config_value_read(data, "profile path column", - CONFIG_PROFILE_PATH_DEFAULT), - config_value_read(data, "acct desc column", - CONFIG_ACCT_DESC_DEFAULT), - config_value_read(data, "workstations column", - CONFIG_WORKSTATIONS_DEFAULT), - config_value_read(data, "unknown string column", - CONFIG_UNKNOWN_STR_DEFAULT), - config_value_read(data, "munged dial column", - CONFIG_MUNGED_DIAL_DEFAULT), - config_value_read(data, "uid column", CONFIG_UID_DEFAULT), - config_value_read(data, "gid column", CONFIG_GID_DEFAULT), - config_value_read(data, "user sid column", - CONFIG_USER_SID_DEFAULT), - config_value_read(data, "group sid column", - CONFIG_GROUP_SID_DEFAULT), - config_value_read(data, "lanman pass column", - CONFIG_LM_PW_DEFAULT), - config_value_read(data, "nt pass column", - CONFIG_NT_PW_DEFAULT), - config_value_read(data, "plain pass column", - CONFIG_PLAIN_PW_DEFAULT), - config_value_read(data, "acct ctrl column", - CONFIG_ACCT_CTRL_DEFAULT), - config_value_read(data, "unknown 3 column", - CONFIG_UNKNOWN_3_DEFAULT), - config_value_read(data, "logon divs column", - CONFIG_LOGON_DIVS_DEFAULT), - config_value_read(data, "hours len column", - CONFIG_HOURS_LEN_DEFAULT), - config_value_read(data, "unknown 5 column", - CONFIG_UNKNOWN_5_DEFAULT), - config_value_read(data, "unknown 6 column", - CONFIG_UNKNOWN_6_DEFAULT), - config_value(data, "table", CONFIG_TABLE_DEFAULT) - ); - DEBUG(5, ("Executing query %s\n", query)); - - ret = mysql_query(data->handle, query); - SAFE_FREE(query); - - if (ret) { - DEBUG(0, - ("Error executing MySQL query %s\n", mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - data->pwent = mysql_store_result(data->handle); - - if (data->pwent == NULL) { - DEBUG(0, - ("Error storing results: %s\n", mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(5, - ("mysqlsam_setsampwent succeeded(%lu results)!\n", - mysql_num_rows(data->pwent))); - - return NT_STATUS_OK; -} - -/*************************************************************** - End enumeration of the passwd list. - ****************************************************************/ - -static void mysqlsam_endsampwent(struct pdb_methods *methods) -{ - struct pdb_mysql_data *data = - (struct pdb_mysql_data *) methods->private_data; - - if (data == NULL) { - DEBUG(0, ("invalid handle!\n")); - return; - } - - if (data->pwent != NULL) - mysql_free_result(data->pwent); - - data->pwent = NULL; - - DEBUG(5, ("mysql_endsampwent called\n")); -} - -/***************************************************************** - Get one SAM_ACCOUNT from the list (next in line) - *****************************************************************/ - -static NTSTATUS mysqlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user) -{ - struct pdb_mysql_data *data; - - SET_DATA(data, methods); - - if (data->pwent == NULL) { - DEBUG(0, ("invalid pwent\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - return row_to_sam_account(data->pwent, user); -} - -static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOUNT * user, - const char *field, const char *sname) -{ - char *esc_sname; - char *query; - NTSTATUS ret; - MYSQL_RES *res; - int mysql_ret; - struct pdb_mysql_data *data; - char *tmp_sname; - - SET_DATA(data, methods); - - esc_sname = malloc(strlen(sname) * 2 + 1); - if (!esc_sname) { - return NT_STATUS_NO_MEMORY; - } - - DEBUG(5, - ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n", - field, sname)); - - tmp_sname = smb_xstrdup(sname); - - /* Escape sname */ - mysql_real_escape_string(data->handle, esc_sname, tmp_sname, - strlen(tmp_sname)); - - SAFE_FREE(tmp_sname); - - if (user == NULL) { - DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n")); - SAFE_FREE(esc_sname); - return NT_STATUS_INVALID_PARAMETER; - } - - asprintf(&query, - "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'", - config_value_read(data, "logon time column", - CONFIG_LOGON_TIME_DEFAULT), - config_value_read(data, "logoff time column", - CONFIG_LOGOFF_TIME_DEFAULT), - config_value_read(data, "kickoff time column", - CONFIG_KICKOFF_TIME_DEFAULT), - config_value_read(data, "pass last set time column", - CONFIG_PASS_LAST_SET_TIME_DEFAULT), - config_value_read(data, "pass can change time column", - CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT), - config_value_read(data, "pass must change time column", - CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT), - config_value_read(data, "username column", - CONFIG_USERNAME_DEFAULT), - config_value_read(data, "domain column", - CONFIG_DOMAIN_DEFAULT), - config_value_read(data, "nt username column", - CONFIG_NT_USERNAME_DEFAULT), - config_value_read(data, "fullname column", - CONFIG_FULLNAME_DEFAULT), - config_value_read(data, "home dir column", - CONFIG_HOME_DIR_DEFAULT), - config_value_read(data, "dir drive column", - CONFIG_DIR_DRIVE_DEFAULT), - config_value_read(data, "logon script column", - CONFIG_LOGON_SCRIPT_DEFAULT), - config_value_read(data, "profile path column", - CONFIG_PROFILE_PATH_DEFAULT), - config_value_read(data, "acct desc column", - CONFIG_ACCT_DESC_DEFAULT), - config_value_read(data, "workstations column", - CONFIG_WORKSTATIONS_DEFAULT), - config_value_read(data, "unknown string column", - CONFIG_UNKNOWN_STR_DEFAULT), - config_value_read(data, "munged dial column", - CONFIG_MUNGED_DIAL_DEFAULT), - config_value_read(data, "uid column", CONFIG_UID_DEFAULT), - config_value_read(data, "gid column", CONFIG_GID_DEFAULT), - config_value_read(data, "user sid column", - CONFIG_USER_SID_DEFAULT), - config_value_read(data, "group sid column", - CONFIG_GROUP_SID_DEFAULT), - config_value_read(data, "lanman pass column", - CONFIG_LM_PW_DEFAULT), - config_value_read(data, "nt pass column", - CONFIG_NT_PW_DEFAULT), - config_value_read(data, "plain pass column", - CONFIG_PLAIN_PW_DEFAULT), - config_value_read(data, "acct ctrl column", - CONFIG_ACCT_CTRL_DEFAULT), - config_value_read(data, "unknown 3 column", - CONFIG_UNKNOWN_3_DEFAULT), - config_value_read(data, "logon divs column", - CONFIG_LOGON_DIVS_DEFAULT), - config_value_read(data, "hours len column", - CONFIG_HOURS_LEN_DEFAULT), - config_value_read(data, "unknown 5 column", - CONFIG_UNKNOWN_5_DEFAULT), - config_value_read(data, "unknown 6 column", - CONFIG_UNKNOWN_6_DEFAULT), - config_value(data, "table", CONFIG_TABLE_DEFAULT), field, - esc_sname); - - SAFE_FREE(esc_sname); - - DEBUG(5, ("Executing query %s\n", query)); - - mysql_ret = mysql_query(data->handle, query); - - SAFE_FREE(query); - - if (mysql_ret) { - DEBUG(0, - ("Error while executing MySQL query %s\n", - mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - res = mysql_store_result(data->handle); - if (res == NULL) { - DEBUG(0, - ("Error storing results: %s\n", mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - ret = row_to_sam_account(res, user); - mysql_free_result(res); - - return ret; -} - -/****************************************************************** - Lookup a name in the SAM database - ******************************************************************/ - -static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user, - const char *sname) -{ - struct pdb_mysql_data *data; - - SET_DATA(data, methods); - - if (!sname) { - DEBUG(0, ("invalid name specified")); - return NT_STATUS_INVALID_PARAMETER; - } - - return mysqlsam_select_by_field(methods, user, - config_value_read(data, "username column", - CONFIG_USERNAME_DEFAULT), sname); -} - - -/*************************************************************************** - Search by sid - **************************************************************************/ - -static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user, - const DOM_SID * sid) -{ - struct pdb_mysql_data *data; - fstring sid_str; - - SET_DATA(data, methods); - - sid_to_string(sid_str, sid); - - return mysqlsam_select_by_field(methods, user, - config_value_read(data, "user sid column", - CONFIG_USER_SID_DEFAULT), sid_str); -} - -/*************************************************************************** - Delete a SAM_ACCOUNT - ****************************************************************************/ - -static NTSTATUS mysqlsam_delete_sam_account(struct pdb_methods *methods, - SAM_ACCOUNT * sam_pass) -{ - const char *sname = pdb_get_username(sam_pass); - char *esc; - char *query; - int ret; - struct pdb_mysql_data *data; - char *tmp_sname; - - SET_DATA(data, methods); - - if (!methods) { - DEBUG(0, ("invalid methods!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - data = (struct pdb_mysql_data *) methods->private_data; - if (!data || !(data->handle)) { - DEBUG(0, ("invalid handle!\n")); - return NT_STATUS_INVALID_HANDLE; - } - - if (!sname) { - DEBUG(0, ("invalid name specified\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - /* Escape sname */ - esc = malloc(strlen(sname) * 2 + 1); - if (!esc) { - DEBUG(0, ("Can't allocate memory to store escaped name\n")); - return NT_STATUS_NO_MEMORY; - } - - tmp_sname = smb_xstrdup(sname); - - mysql_real_escape_string(data->handle, esc, tmp_sname, - strlen(tmp_sname)); - - SAFE_FREE(tmp_sname); - - asprintf(&query, "DELETE FROM %s WHERE %s = '%s'", - config_value(data, "table", CONFIG_TABLE_DEFAULT), - config_value_read(data, "username column", - CONFIG_USERNAME_DEFAULT), esc); - - SAFE_FREE(esc); - - ret = mysql_query(data->handle, query); - - SAFE_FREE(query); - - if (ret) { - DEBUG(0, - ("Error while executing query: %s\n", - mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(5, ("User '%s' deleted\n", sname)); - return NT_STATUS_OK; -} - -static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods, - const SAM_ACCOUNT * newpwd, char isupdate) -{ - pstring temp; - struct pdb_mysql_data *data; - pdb_mysql_query query; - fstring sid_str; - - if (!methods) { - DEBUG(0, ("invalid methods!\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - data = (struct pdb_mysql_data *) methods->private_data; - if (data == NULL || data->handle == NULL) { - DEBUG(0, ("invalid handle!\n")); - return NT_STATUS_INVALID_HANDLE; - } - query.update = isupdate; - - /* I know this is somewhat overkill but only the talloc - * functions have asprint_append and the 'normal' asprintf - * is a GNU extension */ - query.mem_ctx = talloc_init("mysqlsam_replace_sam_account"); - query.part2 = talloc_asprintf(query.mem_ctx, "%s", ""); - if (query.update) { - query.part1 = - talloc_asprintf(query.mem_ctx, "UPDATE %s SET ", - config_value(data, "table", - CONFIG_TABLE_DEFAULT)); - } else { - query.part1 = - talloc_asprintf(query.mem_ctx, "INSERT INTO %s (", - config_value(data, "table", - CONFIG_TABLE_DEFAULT)); - } - - pdb_mysql_int_field(methods, &query, - config_value_write(data, "acct ctrl column", - CONFIG_ACCT_CTRL_DEFAULT), - pdb_get_acct_ctrl(newpwd)); - - if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "logon time column", - CONFIG_LOGON_TIME_DEFAULT), - pdb_get_logon_time(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "logoff time column", - CONFIG_LOGOFF_TIME_DEFAULT), - pdb_get_logoff_time(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "kickoff time column", - CONFIG_KICKOFF_TIME_DEFAULT), - pdb_get_kickoff_time(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "pass can change time column", - CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT), - pdb_get_pass_can_change_time(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "pass must change time column", - CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT), - pdb_get_pass_must_change_time(newpwd)); - } - - if (pdb_get_pass_last_set_time(newpwd)) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "pass last set time column", - CONFIG_PASS_LAST_SET_TIME_DEFAULT), - pdb_get_pass_last_set_time(newpwd)); - } - - if (pdb_get_hours_len(newpwd)) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "hours len column", - CONFIG_HOURS_LEN_DEFAULT), - pdb_get_hours_len(newpwd)); - } - - if (pdb_get_logon_divs(newpwd)) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, - "logon divs column", - CONFIG_LOGON_DIVS_DEFAULT), - pdb_get_logon_divs(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_UID) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, "uid column", - CONFIG_UID_DEFAULT), - pdb_get_uid(newpwd)); - } - - if (pdb_get_init_flags(newpwd, PDB_GID) != PDB_DEFAULT) { - pdb_mysql_int_field(methods, &query, - config_value_write(data, "gid column", - CONFIG_GID_DEFAULT), - pdb_get_gid(newpwd)); - } - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "user sid column", - CONFIG_USER_SID_DEFAULT), - sid_to_string(sid_str, - pdb_get_user_sid(newpwd))); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "group sid column", - CONFIG_GROUP_SID_DEFAULT), - sid_to_string(sid_str, - pdb_get_group_sid(newpwd))); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "username column", - CONFIG_USERNAME_DEFAULT), - pdb_get_username(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "domain column", - CONFIG_DOMAIN_DEFAULT), - pdb_get_domain(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "nt username column", - CONFIG_NT_USERNAME_DEFAULT), - pdb_get_nt_username(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "fullname column", - CONFIG_FULLNAME_DEFAULT), - pdb_get_fullname(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "logon script column", - CONFIG_LOGON_SCRIPT_DEFAULT), - pdb_get_logon_script(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "profile path column", - CONFIG_PROFILE_PATH_DEFAULT), - pdb_get_profile_path(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "dir drive column", - CONFIG_DIR_DRIVE_DEFAULT), - pdb_get_dir_drive(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, "home dir column", - CONFIG_HOME_DIR_DEFAULT), - pdb_get_homedir(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "workstations column", - CONFIG_WORKSTATIONS_DEFAULT), - pdb_get_workstations(newpwd)); - - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "unknown string column", - CONFIG_UNKNOWN_STR_DEFAULT), - pdb_get_workstations(newpwd)); - - pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd), - pdb_get_acct_ctrl(newpwd)); - pdb_mysql_string_field(methods, &query, - config_value_write(data, - "lanman pass column", - CONFIG_LM_PW_DEFAULT), temp); - - pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd), - pdb_get_acct_ctrl(newpwd)); - pdb_mysql_string_field(methods, &query, - config_value_write(data, "nt pass column", - CONFIG_NT_PW_DEFAULT), temp); - - if (query.update) { - query.part1[strlen(query.part1) - 1] = '\0'; - query.part1 = - talloc_asprintf_append(query.mem_ctx, query.part1, - " WHERE %s = '%s'", - config_value_read(data, - "user sid column", - CONFIG_USER_SID_DEFAULT), - sid_to_string(sid_str, pdb_get_user_sid (newpwd))); - } else { - query.part2[strlen(query.part2) - 1] = ')'; - query.part1[strlen(query.part1) - 1] = ')'; - query.part1 = - talloc_asprintf_append(query.mem_ctx, query.part1, - " VALUES (%s", query.part2); - } - - DEBUG(0, ("%s\n", query.part1)); - /* Execute the query */ - if (mysql_query(data->handle, query.part1)) { - DEBUG(0, - ("Error executing %s, %s\n", query.part1, - mysql_error(data->handle))); - return NT_STATUS_INVALID_PARAMETER; - } - talloc_destroy(query.mem_ctx); - return NT_STATUS_OK; -} - -static NTSTATUS mysqlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * newpwd) -{ - return mysqlsam_replace_sam_account(methods, newpwd, 0); -} - -static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods, - SAM_ACCOUNT * newpwd) -{ - return mysqlsam_replace_sam_account(methods, newpwd, 1); -} - -static NTSTATUS mysqlsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) -{ - return get_group_map_from_sid(sid, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) -{ - return get_group_map_from_gid(gid, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) -{ - return get_group_map_from_ntname(name, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_add_group_mapping_entry(struct pdb_methods *methods, - GROUP_MAP *map) -{ - return add_mapping_entry(map, TDB_INSERT) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_update_group_mapping_entry(struct pdb_methods *methods, - GROUP_MAP *map) -{ - return add_mapping_entry(map, TDB_REPLACE) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_delete_group_mapping_entry(struct pdb_methods *methods, - DOM_SID sid) -{ - return group_map_remove(sid) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_enum_group_mapping(struct pdb_methods *methods, - enum SID_NAME_USE sid_name_use, - GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) -{ - return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only, - with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - - -static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method, - const char *location) -{ - NTSTATUS nt_status; - struct pdb_mysql_data *data; - - mysqlsam_debug_level = debug_add_class("mysqlsam"); - if (mysqlsam_debug_level == -1) { - mysqlsam_debug_level = DBGC_ALL; - DEBUG(0, - ("mysqlsam: Couldn't register custom debugging class!\n")); - } - - if (!pdb_context) { - DEBUG(0, ("invalid pdb_methods specified\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!NT_STATUS_IS_OK - (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { - return nt_status; - } - - (*pdb_method)->name = "mysqlsam"; - - (*pdb_method)->setsampwent = mysqlsam_setsampwent; - (*pdb_method)->endsampwent = mysqlsam_endsampwent; - (*pdb_method)->getsampwent = mysqlsam_getsampwent; - (*pdb_method)->getsampwnam = mysqlsam_getsampwnam; - (*pdb_method)->getsampwsid = mysqlsam_getsampwsid; - (*pdb_method)->add_sam_account = mysqlsam_add_sam_account; - (*pdb_method)->update_sam_account = mysqlsam_update_sam_account; - (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account; - (*pdb_method)->getgrsid = mysqlsam_getgrsid; - (*pdb_method)->getgrgid = mysqlsam_getgrgid; - (*pdb_method)->getgrnam = mysqlsam_getgrnam; - (*pdb_method)->add_group_mapping_entry = mysqlsam_add_group_mapping_entry; - (*pdb_method)->update_group_mapping_entry = mysqlsam_update_group_mapping_entry; - (*pdb_method)->delete_group_mapping_entry = mysqlsam_delete_group_mapping_entry; - (*pdb_method)->enum_group_mapping = mysqlsam_enum_group_mapping; - - data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data)); - (*pdb_method)->private_data = data; - data->handle = NULL; - data->pwent = NULL; - - if (!location) { - DEBUG(0, ("No identifier specified. See README for details\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - data->location = smb_xstrdup(location); - - DEBUG(1, - ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n", - config_value(data, "mysql host", CONFIG_HOST_DEFAULT), - config_value(data, "mysql user", CONFIG_USER_DEFAULT), - config_value(data, "mysql password", CONFIG_PASS_DEFAULT), - config_value(data, "mysql database", CONFIG_DB_DEFAULT), - xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT)))); - - /* Do the mysql initialization */ - data->handle = mysql_init(NULL); - if (!data->handle) { - DEBUG(0, ("Failed to connect to server\n")); - return NT_STATUS_UNSUCCESSFUL; - } - /* Process correct entry in $HOME/.my.conf */ - if (!mysql_real_connect(data->handle, - config_value(data, "mysql host", CONFIG_HOST_DEFAULT), - config_value(data, "mysql user", CONFIG_USER_DEFAULT), - config_value(data, "mysql password", CONFIG_PASS_DEFAULT), - config_value(data, "mysql database", CONFIG_DB_DEFAULT), - xatol(config_value (data, "mysql port", CONFIG_PORT_DEFAULT)), - NULL, 0)) { - DEBUG(0, - ("Failed to connect to mysql database: error: %s\n", - mysql_error(data->handle))); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(5, ("Connected to mysql db\n")); - - return NT_STATUS_OK; -} - -int init_module(void); - -int init_module() -{ - if(smb_register_passdb("mysql", mysqlsam_init, PASSDB_INTERFACE_VERSION)) - return 0; - - return 1; -} diff --git a/source4/modules/vfs_audit.c b/source4/modules/vfs_audit.c deleted file mode 100644 index b99d93d0f0..0000000000 --- a/source4/modules/vfs_audit.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Auditing VFS module for samba. Log selected file operations to syslog - * facility. - * - * Copyright (C) Tim Potter, 1999-2000 - * Copyright (C) Alexander Bokovoy, 2002 - * - * 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 "config.h" -#include <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#include <syslog.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> - -#ifndef SYSLOG_FACILITY -#define SYSLOG_FACILITY LOG_USER -#endif - -#ifndef SYSLOG_PRIORITY -#define SYSLOG_PRIORITY LOG_NOTICE -#endif - -/* Function prototypes */ - -static int audit_connect(struct tcon_context *conn, const char *svc, const char *user); -static void audit_disconnect(struct tcon_context *conn); -static DIR *audit_opendir(struct tcon_context *conn, const char *fname); -static int audit_mkdir(struct tcon_context *conn, const char *path, mode_t mode); -static int audit_rmdir(struct tcon_context *conn, const char *path); -static int audit_open(struct tcon_context *conn, const char *fname, int flags, mode_t mode); -static int audit_close(struct files_struct *fsp, int fd); -static int audit_rename(struct tcon_context *conn, const char *old, const char *new); -static int audit_unlink(struct tcon_context *conn, const char *path); -static int audit_chmod(struct tcon_context *conn, const char *path, mode_t mode); -static int audit_chmod_acl(struct tcon_context *conn, const char *name, mode_t mode); -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode); -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode); - -/* VFS operations */ - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *audit_handle; - -static vfs_op_tuple audit_ops[] = { - - /* Disk operations */ - - {audit_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, - {audit_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, - - /* Directory operations */ - - {audit_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, - {audit_mkdir, SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, - {audit_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, - - /* File operations */ - - {audit_open, SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, - {audit_close, SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, - {audit_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, - {audit_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, - {audit_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod, SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - - /* Finish VFS operations definition */ - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ - -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - audit_handle = vfs_handle; - - openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY); - syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n"); - return audit_ops; -} - -/* VFS finalization function. */ -void vfs_done(struct tcon_context *conn) -{ - syslog(SYSLOG_PRIORITY, "VFS_DONE: vfs module unloaded\n"); -} - -/* Implementation of vfs_ops. Pass everything on to the default - operation but log event first. */ - -static int audit_connect(struct tcon_context *conn, const char *svc, const char *user) -{ - syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", - svc, user); - - return default_vfs_ops.connect(conn, svc, user); -} - -static void audit_disconnect(struct tcon_context *conn) -{ - syslog(SYSLOG_PRIORITY, "disconnected\n"); - default_vfs_ops.disconnect(conn); -} - -static DIR *audit_opendir(struct tcon_context *conn, const char *fname) -{ - DIR *result = default_vfs_ops.opendir(conn, fname); - - syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n", - fname, - (result == NULL) ? "failed: " : "", - (result == NULL) ? strerror(errno) : ""); - - return result; -} - -static int audit_mkdir(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result = default_vfs_ops.mkdir(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_rmdir(struct tcon_context *conn, const char *path) -{ - int result = default_vfs_ops.rmdir(conn, path); - - syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_open(struct tcon_context *conn, const char *fname, int flags, mode_t mode) -{ - int result = default_vfs_ops.open(conn, fname, flags, mode); - - syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", - fname, result, - ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_close(struct files_struct *fsp, int fd) -{ - int result = default_vfs_ops.close(fsp, fd); - - syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n", - fd, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_rename(struct tcon_context *conn, const char *old, const char *new) -{ - int result = default_vfs_ops.rename(conn, old, new); - - syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n", - old, new, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_unlink(struct tcon_context *conn, const char *path) -{ - int result = default_vfs_ops.unlink(conn, path); - - syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_chmod(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result = default_vfs_ops.chmod(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_chmod_acl(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result; - - if ( !default_vfs_ops.chmod_acl ) - return 0; - - result = default_vfs_ops.chmod_acl(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) -{ - int result = default_vfs_ops.fchmod(fsp, fd, mode); - - syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} - -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) -{ - int result; - - if ( !default_vfs_ops.fchmod_acl ) - return 0; - - result = default_vfs_ops.fchmod_acl(fsp, fd, mode); - - syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - - return result; -} diff --git a/source4/modules/vfs_extd_audit.c b/source4/modules/vfs_extd_audit.c deleted file mode 100644 index e9b6ed5455..0000000000 --- a/source4/modules/vfs_extd_audit.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Auditing VFS module for samba. Log selected file operations to syslog - * facility. - * - * Copyright (C) Tim Potter, 1999-2000 - * Copyright (C) Alexander Bokovoy, 2002 - * Copyright (C) John H Terpstra, 2003 - * - * 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 "config.h" -#include <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#include <syslog.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> - -#ifndef SYSLOG_FACILITY -#define SYSLOG_FACILITY LOG_USER -#endif - -#ifndef SYSLOG_PRIORITY -#define SYSLOG_PRIORITY LOG_NOTICE -#endif - -/* Function prototypes */ - -static int audit_connect(struct tcon_context *conn, const char *svc, const char *user); -static void audit_disconnect(struct tcon_context *conn); -static DIR *audit_opendir(struct tcon_context *conn, const char *fname); -static int audit_mkdir(struct tcon_context *conn, const char *path, mode_t mode); -static int audit_rmdir(struct tcon_context *conn, const char *path); -static int audit_open(struct tcon_context *conn, const char *fname, int flags, mode_t mode); -static int audit_close(struct files_struct *fsp, int fd); -static int audit_rename(struct tcon_context *conn, const char *old, const char *new); -static int audit_unlink(struct tcon_context *conn, const char *path); -static int audit_chmod(struct tcon_context *conn, const char *path, mode_t mode); -static int audit_chmod_acl(struct tcon_context *conn, const char *name, mode_t mode); -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode); -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode); - -/* VFS operations */ - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *audit_handle; - -static vfs_op_tuple audit_ops[] = { - - /* Disk operations */ - - {audit_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, - {audit_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, - - /* Directory operations */ - - {audit_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, - {audit_mkdir, SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, - {audit_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, - - /* File operations */ - - {audit_open, SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, - {audit_close, SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, - {audit_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, - {audit_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, - {audit_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod, SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - - /* Finish VFS operations definition */ - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ - -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - audit_handle = vfs_handle; - - openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY); - syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n"); - - return audit_ops; -} - -/* VFS finalization function. */ - -void vfs_done(struct tcon_context *conn) -{ - syslog(SYSLOG_PRIORITY, "VFS_DONE: vfs module unloaded\n"); -} - -/* Implementation of vfs_ops. Pass everything on to the default - operation but log event first. */ - -static int audit_connect(struct tcon_context *conn, const char *svc, const char *user) -{ - syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", - svc, user); - DEBUG(10, ("Connected to service %s as user %s\n", - svc, user)); - - return default_vfs_ops.connect(conn, svc, user); -} - -static void audit_disconnect(struct tcon_context *conn) -{ - syslog(SYSLOG_PRIORITY, "disconnected\n"); - DEBUG(10, ("Disconnected from VFS module extd_audit\n")); - - default_vfs_ops.disconnect(conn); -} - -static DIR *audit_opendir(struct tcon_context *conn, const char *fname) -{ - DIR *result = default_vfs_ops.opendir(conn, fname); - - syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n", - fname, - (result == NULL) ? "failed: " : "", - (result == NULL) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: opendir %s %s %s", - fname, - (result == NULL) ? "failed: " : "", - (result == NULL) ? strerror(errno) : "")); - - return result; -} - -static int audit_mkdir(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result = default_vfs_ops.mkdir(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(0, ("vfs_extd_audit: mkdir %s %s %s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_rmdir(struct tcon_context *conn, const char *path) -{ - int result = default_vfs_ops.rmdir(conn, path); - - syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(0, ("vfs_extd_audit: rmdir %s %s %s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_open(struct tcon_context *conn, const char *fname, int flags, mode_t mode) -{ - int result = default_vfs_ops.open(conn, fname, flags, mode); - - syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", - fname, result, - ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(2, ("vfs_extd_audit: open %s %s %s\n", - fname, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_close(struct files_struct *fsp, int fd) -{ - int result = default_vfs_ops.close(fsp, fd); - - syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n", - fd, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(2, ("vfs_extd_audit: close fd %d %s %s\n", - fd, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_rename(struct tcon_context *conn, const char *old, const char *new) -{ - int result = default_vfs_ops.rename(conn, old, new); - - syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n", - old, new, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: rename old: %s new: %s %s %s\n", - old, new, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_unlink(struct tcon_context *conn, const char *path) -{ - int result = default_vfs_ops.unlink(conn, path); - - syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(0, ("vfs_extd_audit: unlink %s %s %s\n", - path, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_chmod(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result = default_vfs_ops.chmod(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: chmod %s mode 0x%x %s %s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_chmod_acl(struct tcon_context *conn, const char *path, mode_t mode) -{ - int result = default_vfs_ops.chmod_acl(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: chmod_acl %s mode 0x%x %s %s\n", - path, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) -{ - int result = default_vfs_ops.fchmod(fsp, fd, mode); - - syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: fchmod %s mode 0x%x %s %s", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} - -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) -{ - int result = default_vfs_ops.fchmod_acl(fsp, fd, mode); - - syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: fchmod_acl %s mode 0x%x %s %s", - fsp->fsp_name, mode, - (result < 0) ? "failed: " : "", - (result < 0) ? strerror(errno) : "")); - - return result; -} diff --git a/source4/modules/vfs_fake_perms.c b/source4/modules/vfs_fake_perms.c deleted file mode 100644 index 63ef66c591..0000000000 --- a/source4/modules/vfs_fake_perms.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Fake Perms VFS module. Implements passthrough operation of all VFS - * calls to disk functions, except for file permissions, which are now - * mode 0700 for the current uid/gid. - * - * Copyright (C) Tim Potter, 1999-2000 - * Copyright (C) Alexander Bokovoy, 2002 - * Copyright (C) Andrew Bartlett, 2002 - * - * 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 "config.h" - -#include <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> - -#include <includes.h> -#include <vfs.h> - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *fake_perms_handle; /* use fake_perms_handle->data for storing per-instance private data */ - -static int fake_perms_connect(struct tcon_context *conn, const char *service, const char *user) -{ - return default_vfs_ops.connect(conn, service, user); -} - -static void fake_perms_disconnect(struct tcon_context *conn) -{ - default_vfs_ops.disconnect(conn); -} - -static SMB_BIG_UINT fake_perms_disk_free(struct tcon_context *conn, const char *path, - BOOL small_query, SMB_BIG_UINT *bsize, - SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) -{ - return default_vfs_ops.disk_free(conn, path, small_query, bsize, - dfree, dsize); -} - -static DIR *fake_perms_opendir(struct tcon_context *conn, const char *fname) -{ - return default_vfs_ops.opendir(conn, fname); -} - -static struct dirent *fake_perms_readdir(struct tcon_context *conn, DIR *dirp) -{ - return default_vfs_ops.readdir(conn, dirp); -} - -static int fake_perms_mkdir(struct tcon_context *conn, const char *path, mode_t mode) -{ - return default_vfs_ops.mkdir(conn, path, mode); -} - -static int fake_perms_rmdir(struct tcon_context *conn, const char *path) -{ - return default_vfs_ops.rmdir(conn, path); -} - -static int fake_perms_closedir(struct tcon_context *conn, DIR *dir) -{ - return default_vfs_ops.closedir(conn, dir); -} - -static int fake_perms_open(struct tcon_context *conn, const char *fname, int flags, mode_t mode) -{ - return default_vfs_ops.open(conn, fname, flags, mode); -} - -static int fake_perms_close(struct files_struct *fsp, int fd) -{ - return default_vfs_ops.close(fsp, fd); -} - -static ssize_t fake_perms_read(struct files_struct *fsp, int fd, void *data, size_t n) -{ - return default_vfs_ops.read(fsp, fd, data, n); -} - -static ssize_t fake_perms_write(struct files_struct *fsp, int fd, const void *data, size_t n) -{ - return default_vfs_ops.write(fsp, fd, data, n); -} - -static SMB_OFF_T fake_perms_lseek(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) -{ - return default_vfs_ops.lseek(fsp, filedes, offset, whence); -} - -static int fake_perms_rename(struct tcon_context *conn, const char *old, const char *new) -{ - return default_vfs_ops.rename(conn, old, new); -} - -static int fake_perms_fsync(struct files_struct *fsp, int fd) -{ - return default_vfs_ops.fsync(fsp, fd); -} - -static int fake_perms_stat(struct tcon_context *conn, const char *fname, SMB_STRUCT_STAT *sbuf) -{ - int ret = default_vfs_ops.stat(conn, fname, sbuf); - extern struct current_user current_user; - - if (S_ISDIR(sbuf->st_mode)) { - sbuf->st_mode = S_IFDIR | S_IRWXU; - } else { - sbuf->st_mode = S_IRWXU; - } - sbuf->st_uid = current_user.uid; - sbuf->st_gid = current_user.gid; - return ret; -} - -static int fake_perms_fstat(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) -{ - return default_vfs_ops.fstat(fsp, fd, sbuf); -} - -static int fake_perms_lstat(struct tcon_context *conn, const char *path, SMB_STRUCT_STAT *sbuf) -{ - return default_vfs_ops.lstat(conn, path, sbuf); -} - -static int fake_perms_unlink(struct tcon_context *conn, const char *path) -{ - return default_vfs_ops.unlink(conn, path); -} - -static int fake_perms_chmod(struct tcon_context *conn, const char *path, mode_t mode) -{ - return default_vfs_ops.chmod(conn, path, mode); -} - -static int fake_perms_fchmod(struct files_struct *fsp, int fd, mode_t mode) -{ - return default_vfs_ops.fchmod(fsp, fd, mode); -} - -static int fake_perms_chown(struct tcon_context *conn, const char *path, uid_t uid, gid_t gid) -{ - return default_vfs_ops.chown(conn, path, uid, gid); -} - -static int fake_perms_fchown(struct files_struct *fsp, int fd, uid_t uid, gid_t gid) -{ - return default_vfs_ops.fchown(fsp, fd, uid, gid); -} - -static int fake_perms_chdir(struct tcon_context *conn, const char *path) -{ - return default_vfs_ops.chdir(conn, path); -} - -static char *fake_perms_getwd(struct tcon_context *conn, char *buf) -{ - return default_vfs_ops.getwd(conn, buf); -} - -static int fake_perms_utime(struct tcon_context *conn, const char *path, struct utimbuf *times) -{ - return default_vfs_ops.utime(conn, path, times); -} - -static int fake_perms_ftruncate(struct files_struct *fsp, int fd, SMB_OFF_T offset) -{ - return default_vfs_ops.ftruncate(fsp, fd, offset); -} - -static BOOL fake_perms_lock(struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) -{ - return default_vfs_ops.lock(fsp, fd, op, offset, count, type); -} - -static BOOL fake_perms_symlink(struct tcon_context *conn, const char *oldpath, const char *newpath) -{ - return default_vfs_ops.symlink(conn, oldpath, newpath); -} - -static BOOL fake_perms_readlink(struct tcon_context *conn, const char *path, char *buf, size_t bufsiz) -{ - return default_vfs_ops.readlink(conn, path, buf, bufsiz); -} - -static int fake_perms_link(struct tcon_context *conn, const char *oldpath, const char *newpath) -{ - return default_vfs_ops.link(conn, oldpath, newpath); -} - -static int fake_perms_mknod(struct tcon_context *conn, const char *path, mode_t mode, SMB_DEV_T dev) -{ - return default_vfs_ops.mknod(conn, path, mode, dev); -} - -static char *fake_perms_realpath(struct tcon_context *conn, const char *path, char *resolved_path) -{ - return default_vfs_ops.realpath(conn, path, resolved_path); -} - -static size_t fake_perms_fget_nt_acl(struct files_struct *fsp, int fd, struct security_descriptor_info **ppdesc) -{ - return default_vfs_ops.fget_nt_acl(fsp, fd, ppdesc); -} - -static size_t fake_perms_get_nt_acl(struct files_struct *fsp, const char *name, struct security_descriptor_info **ppdesc) -{ - return default_vfs_ops.get_nt_acl(fsp, name, ppdesc); -} - -static BOOL fake_perms_fset_nt_acl(struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd) -{ - return default_vfs_ops.fset_nt_acl(fsp, fd, security_info_sent, psd); -} - -static BOOL fake_perms_set_nt_acl(struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd) -{ - return default_vfs_ops.set_nt_acl(fsp, name, security_info_sent, psd); -} - -static BOOL fake_perms_chmod_acl(struct tcon_context *conn, const char *name, mode_t mode) -{ - return default_vfs_ops.chmod_acl(conn, name, mode); -} - -static BOOL fake_perms_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) -{ - return default_vfs_ops.fchmod_acl(fsp, fd, mode); -} - -static int fake_perms_sys_acl_get_entry(struct tcon_context *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return default_vfs_ops.sys_acl_get_entry(conn, theacl, entry_id, entry_p); -} - -static int fake_perms_sys_acl_get_tag_type(struct tcon_context *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return default_vfs_ops.sys_acl_get_tag_type(conn, entry_d, tag_type_p); -} - -static int fake_perms_sys_acl_get_permset(struct tcon_context *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return default_vfs_ops.sys_acl_get_permset(conn, entry_d, permset_p); -} - -static void *fake_perms_sys_acl_get_qualifier(struct tcon_context *conn, SMB_ACL_ENTRY_T entry_d) -{ - return default_vfs_ops.sys_acl_get_qualifier(conn, entry_d); -} - -static SMB_ACL_T fake_perms_sys_acl_get_file(struct tcon_context *conn, const char *path_p, SMB_ACL_TYPE_T type) -{ - return default_vfs_ops.sys_acl_get_file(conn, path_p, type); -} - -static SMB_ACL_T fake_perms_sys_acl_get_fd(struct files_struct *fsp, int fd) -{ - return default_vfs_ops.sys_acl_get_fd(fsp, fd); -} - -static int fake_perms_sys_acl_clear_perms(struct tcon_context *conn, SMB_ACL_PERMSET_T permset) -{ - return default_vfs_ops.sys_acl_clear_perms(conn, permset); -} - -static int fake_perms_sys_acl_add_perm(struct tcon_context *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return default_vfs_ops.sys_acl_add_perm(conn, permset, perm); -} - -static char *fake_perms_sys_acl_to_text(struct tcon_context *conn, SMB_ACL_T theacl, ssize_t *plen) -{ - return default_vfs_ops.sys_acl_to_text(conn, theacl, plen); -} - -static SMB_ACL_T fake_perms_sys_acl_init(struct tcon_context *conn, int count) -{ - return default_vfs_ops.sys_acl_init(conn, count); -} - -static int fake_perms_sys_acl_create_entry(struct tcon_context *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return default_vfs_ops.sys_acl_create_entry(conn, pacl, pentry); -} - -static int fake_perms_sys_acl_set_tag_type(struct tcon_context *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return default_vfs_ops.sys_acl_set_tag_type(conn, entry, tagtype); -} - -static int fake_perms_sys_acl_set_qualifier(struct tcon_context *conn, SMB_ACL_ENTRY_T entry, void *qual) -{ - return default_vfs_ops.sys_acl_set_qualifier(conn, entry, qual); -} - -static int fake_perms_sys_acl_set_permset(struct tcon_context *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return default_vfs_ops.sys_acl_set_permset(conn, entry, permset); -} - -static int fake_perms_sys_acl_valid(struct tcon_context *conn, SMB_ACL_T theacl ) -{ - return default_vfs_ops.sys_acl_valid(conn, theacl ); -} - -static int fake_perms_sys_acl_set_file(struct tcon_context *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return default_vfs_ops.sys_acl_set_file(conn, name, acltype, theacl); -} - -static int fake_perms_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl) -{ - return default_vfs_ops.sys_acl_set_fd(fsp, fd, theacl); -} - -static int fake_perms_sys_acl_delete_def_file(struct tcon_context *conn, const char *path) -{ - return default_vfs_ops.sys_acl_delete_def_file(conn, path); -} - -static int fake_perms_sys_acl_get_perm(struct tcon_context *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return default_vfs_ops.sys_acl_get_perm(conn, permset, perm); -} - -static int fake_perms_sys_acl_free_text(struct tcon_context *conn, char *text) -{ - return default_vfs_ops.sys_acl_free_text(conn, text); -} - -static int fake_perms_sys_acl_free_acl(struct tcon_context *conn, SMB_ACL_T posix_acl) -{ - return default_vfs_ops.sys_acl_free_acl(conn, posix_acl); -} - -static int fake_perms_sys_acl_free_qualifier(struct tcon_context *conn, void *qualifier, SMB_ACL_TAG_T tagtype) -{ - return default_vfs_ops.sys_acl_free_qualifier(conn, qualifier, tagtype); -} - - -/* VFS operations structure */ - -static vfs_op_tuple fake_perms_ops[] = { - - /* Disk operations */ - - {fake_perms_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_disk_free, SMB_VFS_OP_DISK_FREE, SMB_VFS_LAYER_TRANSPARENT}, - - /* Directory operations */ - - {fake_perms_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_readdir, SMB_VFS_OP_READDIR, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_mkdir, SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_closedir, SMB_VFS_OP_CLOSEDIR, SMB_VFS_LAYER_TRANSPARENT}, - - /* File operations */ - - {fake_perms_open, SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_close, SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_read, SMB_VFS_OP_READ, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_write, SMB_VFS_OP_WRITE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_lseek, SMB_VFS_OP_LSEEK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fsync, SMB_VFS_OP_FSYNC, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_stat, SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fstat, SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_lstat, SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fchmod, SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fchown, SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_chdir, SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_getwd, SMB_VFS_OP_GETWD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_utime, SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_ftruncate, SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_lock, SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_symlink, SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_readlink, SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_link, SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_mknod, SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_realpath, SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_TRANSPARENT}, - - /* NT File ACL operations */ - - {fake_perms_fget_nt_acl, SMB_VFS_OP_FGET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_get_nt_acl, SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fset_nt_acl, SMB_VFS_OP_FSET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_set_nt_acl, SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - - /* POSIX ACL operations */ - - {fake_perms_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT}, - - {fake_perms_sys_acl_get_entry, SMB_VFS_OP_SYS_ACL_GET_ENTRY, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_tag_type, SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_permset, SMB_VFS_OP_SYS_ACL_GET_PERMSET, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_qualifier, SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_file, SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_fd, SMB_VFS_OP_SYS_ACL_GET_FD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_clear_perms, SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_add_perm, SMB_VFS_OP_SYS_ACL_ADD_PERM, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_to_text, SMB_VFS_OP_SYS_ACL_TO_TEXT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_init, SMB_VFS_OP_SYS_ACL_INIT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_create_entry, SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_tag_type, SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_qualifier, SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_permset, SMB_VFS_OP_SYS_ACL_SET_PERMSET, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_valid, SMB_VFS_OP_SYS_ACL_VALID, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_file, SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_fd, SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_delete_def_file, SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_perm, SMB_VFS_OP_SYS_ACL_GET_PERM, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_text, SMB_VFS_OP_SYS_ACL_FREE_TEXT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_acl, SMB_VFS_OP_SYS_ACL_FREE_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_qualifier, SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/* VFS initialisation - return initialized vfs_op_tuple array back to Samba */ - -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - DEBUG(3, ("Initialising default vfs hooks\n")); - - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - /* Remember vfs_handle for further allocation and referencing of private - information in vfs_handle->data - */ - fake_perms_handle = vfs_handle; - return fake_perms_ops; -} - -/* VFS finalization function */ -void vfs_done(struct tcon_context *conn) -{ - DEBUG(3, ("Finalizing default vfs hooks\n")); -} diff --git a/source4/modules/vfs_netatalk.c b/source4/modules/vfs_netatalk.c deleted file mode 100644 index 0c1eb8d15e..0000000000 --- a/source4/modules/vfs_netatalk.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * AppleTalk VFS module for Samba-3.x - * - * Copyright (C) Alexei Kotovich, 2002 - * - * 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 "config.h" -#include <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> - -#define APPLEDOUBLE ".AppleDouble" -#define ADOUBLEMODE 0777 - -/* atalk functions */ - -static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, - const char *fname, char **adbl_path, char **orig_path, - SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info); - -static int atalk_unlink_file(const char *path); - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *atalk_handle; - -static int atalk_get_path_ptr(char *path) -{ - int i = 0; - int ptr = 0; - - for (i = 0; path[i]; i ++) { - if (path[i] == '/') - ptr = i; - /* get out some 'spam';) from win32's file name */ - else if (path[i] == ':') { - path[i] = '\0'; - break; - } - } - - return ptr; -} - -static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, const char *fname, - char **adbl_path, char **orig_path, - SMB_STRUCT_STAT *adbl_info, SMB_STRUCT_STAT *orig_info) -{ - int ptr0 = 0; - int ptr1 = 0; - char *dname = 0; - char *name = 0; - - if (!ctx || !path || !fname || !adbl_path || !orig_path || - !adbl_info || !orig_info) - return -1; -#if 0 - DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname)); -#endif - if (strstr(path, APPLEDOUBLE) || strstr(fname, APPLEDOUBLE)) { - DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE)); - return -1; - } - - if (fname[0] == '.') ptr0 ++; - if (fname[1] == '/') ptr0 ++; - - *orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]); - - /* get pointer to last '/' */ - ptr1 = atalk_get_path_ptr(*orig_path); - - sys_lstat(*orig_path, orig_info); - - if (S_ISDIR(orig_info->st_mode)) { - *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", - path, &fname[ptr0], APPLEDOUBLE); - } else { - dname = talloc_strdup(ctx, *orig_path); - dname[ptr1] = '\0'; - name = *orig_path; - *adbl_path = talloc_asprintf(ctx, "%s/%s/%s", - dname, APPLEDOUBLE, &name[ptr1 + 1]); - } -#if 0 - DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); -#endif - sys_lstat(*adbl_path, adbl_info); - return 0; -} - -static int atalk_unlink_file(const char *path) -{ - int ret = 0; - - become_root(); - ret = unlink(path); - unbecome_root(); - - return ret; -} - -static void atalk_add_to_list(name_compare_entry **list) -{ - int i, count = 0; - name_compare_entry *new_list = 0; - name_compare_entry *cur_list = 0; - - cur_list = *list; - - if (cur_list) { - for (i = 0, count = 0; cur_list[i].name; i ++, count ++) { - if (strstr(cur_list[i].name, APPLEDOUBLE)) - return; - } - } - - if (!(new_list = calloc(1, - (count == 0 ? 1 : count + 1) * sizeof(name_compare_entry)))) - return; - - for (i = 0; i < count; i ++) { - new_list[i].name = strdup(cur_list[i].name); - new_list[i].is_wild = cur_list[i].is_wild; - } - - new_list[i].name = strdup(APPLEDOUBLE); - new_list[i].is_wild = False; - - free_namearray(*list); - - *list = new_list; - new_list = 0; - cur_list = 0; -} - -static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) -{ - char *dpath; - struct dirent *dent = 0; - DIR *dir; - - if (!path) return; - - dir = opendir(path); - if (!dir) return; - - while (NULL != (dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - if (!(dpath = talloc_asprintf(ctx, "%s/%s", - path, dent->d_name))) - continue; - atalk_unlink_file(dpath); - } - - closedir(dir); -} - -/* Disk operations */ - -/* Directory operations */ - -DIR *atalk_opendir(struct tcon_context *conn, const char *fname) -{ - DIR *ret = 0; - - ret = default_vfs_ops.opendir(conn, fname); - - /* - * when we try to perform delete operation upon file which has fork - * in ./.AppleDouble and this directory wasn't hidden by Samba, - * MS Windows explorer causes the error: "Cannot find the specified file" - * There is some workaround to avoid this situation, i.e. if - * connection has not .AppleDouble entry in either veto or hide - * list then it would be nice to add one. - */ - - atalk_add_to_list(&conn->hide_list); - atalk_add_to_list(&conn->veto_list); - - return ret; -} - -static int atalk_rmdir(struct tcon_context *conn, const char *path) -{ - BOOL add = False; - TALLOC_CTX *ctx = 0; - char *dpath; - - if (!conn || !conn->origpath || !path) goto exit_rmdir; - - /* due to there is no way to change bDeleteVetoFiles variable - * from this module, gotta use talloc stuff.. - */ - - strstr(path, APPLEDOUBLE) ? (add = False) : (add = True); - - if (!(ctx = talloc_init("remove_directory"))) - goto exit_rmdir; - - if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", - conn->origpath, path, add ? "/"APPLEDOUBLE : ""))) - goto exit_rmdir; - - atalk_rrmdir(ctx, dpath); - -exit_rmdir: - talloc_destroy(ctx); - return default_vfs_ops.rmdir(conn, path); -} - -/* File operations */ - -static int atalk_rename(struct tcon_context *conn, const char *old, const char *new) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.rename(conn, old, new); - - if (!conn || !old) return ret; - - if (!(ctx = talloc_init("rename_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, old, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); - goto exit_rename; - } - - atalk_unlink_file(adbl_path); - -exit_rename: - talloc_destroy(ctx); - return ret; -} - -static int atalk_unlink(struct tcon_context *conn, const char *path) -{ - int ret = 0, i; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.unlink(conn, path); - - if (!conn || !path) return ret; - - /* no .AppleDouble sync if veto or hide list is empty, - * otherwise "Cannot find the specified file" error will be caused - */ - - if (!conn->veto_list) return ret; - if (!conn->hide_list) return ret; - - for (i = 0; conn->veto_list[i].name; i ++) { - if (strstr(conn->veto_list[i].name, APPLEDOUBLE)) - break; - } - - if (!conn->veto_list[i].name) { - for (i = 0; conn->hide_list[i].name; i ++) { - if (strstr(conn->hide_list[i].name, APPLEDOUBLE)) - break; - else { - DEBUG(3, ("ATALK: %s is not hidden, skipped..\n", - APPLEDOUBLE)); - return ret; - } - } - } - - if (!(ctx = talloc_init("unlink_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); - goto exit_unlink; - } - - atalk_unlink_file(adbl_path); - -exit_unlink: - talloc_destroy(ctx); - return ret; -} - -static int atalk_chmod(struct tcon_context *conn, const char *path, mode_t mode) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.chmod(conn, path, mode); - - if (!conn || !path) return ret; - - if (!(ctx = talloc_init("chmod_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); - goto exit_chmod; - } - - chmod(adbl_path, ADOUBLEMODE); - -exit_chmod: - talloc_destroy(ctx); - return ret; -} - -static int atalk_chown(struct tcon_context *conn, const char *path, uid_t uid, gid_t gid) -{ - int ret = 0; - char *adbl_path = 0; - char *orig_path = 0; - SMB_STRUCT_STAT adbl_info; - SMB_STRUCT_STAT orig_info; - TALLOC_CTX *ctx; - - ret = default_vfs_ops.chown(conn, path, uid, gid); - - if (!conn || !path) return ret; - - if (!(ctx = talloc_init("chown_file"))) - return ret; - - if (atalk_build_paths(ctx, conn->origpath, path, &adbl_path, &orig_path, - &adbl_info, &orig_info) != 0) - return ret; - - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { - DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); - goto exit_chown; - } - - chown(adbl_path, uid, gid); - -exit_chown: - talloc_destroy(ctx); - return ret; -} - -static vfs_op_tuple atalk_ops[] = { - - /* Directory operations */ - - {atalk_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, - - /* File operations */ - - {atalk_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, - - /* Finish VFS operations definition */ - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - atalk_handle = vfs_handle; - - DEBUG(3, ("ATALK: vfs module loaded\n")); - return atalk_ops; -} - -/* VFS finalization function. */ -void vfs_done(struct tcon_context *conn) -{ - DEBUG(3, ("ATALK: vfs module unloaded\n")); -} diff --git a/source4/modules/vfs_recycle.c b/source4/modules/vfs_recycle.c deleted file mode 100644 index 2a017aca04..0000000000 --- a/source4/modules/vfs_recycle.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * Recycle bin VFS module for Samba. - * - * Copyright (C) 2001, Brandon Stone, Amherst College, <bbstone@amherst.edu>. - * Copyright (C) 2002, Jeremy Allison - modified to make a VFS module. - * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption, - * Copyright (C) 2002, Juergen Hasch - added some options. - * Copyright (C) 2002, Simo Sorce - * - * 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" - -#define ALLOC_CHECK(ptr, label) do { if ((ptr) == NULL) { DEBUG(0, ("recycle.bin: out of memory!\n")); errno = ENOMEM; goto label; } } while(0) - -static int vfs_recycle_debug_level = DBGC_VFS; - -#undef DBGC_CLASS -#define DBGC_CLASS vfs_recycle_debug_level - -static const char *delimiter = "|"; /* delimiter for options */ - -/* One per connection */ - -typedef struct recycle_bin_struct -{ - TALLOC_CTX *mem_ctx; - char *repository; /* name of the recycle bin directory */ - BOOL keep_dir_tree; /* keep directory structure of deleted file in recycle bin */ - BOOL versions; /* create versions of deleted files with identical name */ - BOOL touch; /* touch access date of deleted file */ - char *exclude; /* which files to exclude */ - char *exclude_dir; /* which directories to exclude */ - char *noversions; /* which files to exclude from versioning */ - SMB_OFF_T maxsize; /* maximum file size to be saved */ -} recycle_bin_struct; - -typedef struct recycle_bin_connections { - int conn; - recycle_bin_struct *data; - struct recycle_bin_connections *next; -} recycle_bin_connections; - -typedef struct recycle_bin_private_data { - TALLOC_CTX *mem_ctx; - recycle_bin_connections *conns; -} recycle_bin_private_data; - -struct smb_vfs_handle_struct *recycle_bin_private_handle; - -/* VFS operations */ -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ - -static int recycle_connect(struct tcon_context *conn, const char *service, const char *user); -static void recycle_disconnect(struct tcon_context *conn); -static int recycle_unlink(struct tcon_context *, const char *); - -#define VFS_OP(x) ((void *) x) - -static vfs_op_tuple recycle_ops[] = { - - /* Disk operations */ - {VFS_OP(recycle_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {VFS_OP(recycle_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, - - /* File operations */ - {VFS_OP(recycle_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} -}; - -/** - * VFS initialisation function. - * - * @retval initialised vfs_op_tuple array - **/ -vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - TALLOC_CTX *mem_ctx = NULL; - - DEBUG(10, ("Initializing VFS module recycle\n")); - *vfs_version = SMB_VFS_INTERFACE_VERSION; - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin"); - if (vfs_recycle_debug_level == -1) { - vfs_recycle_debug_level = DBGC_VFS; - DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n")); - } else { - DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level)); - } - - recycle_bin_private_handle = vfs_handle; - if (!(mem_ctx = talloc_init("recycle bin data"))) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return NULL; - } - - recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data)); - if (recycle_bin_private_handle->data == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return NULL; - } - ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx; - ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL; - - return recycle_ops; -} - -/** - * VFS finalization function. - * - **/ -void vfs_done(void) -{ - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; - - DEBUG(10, ("Unloading/Cleaning VFS module recycle bin\n")); - - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return; - } - - if (recdata) { - if (recdata->conns) { - recconn = recdata->conns; - while (recconn) { - talloc_destroy(recconn->data->mem_ctx); - recconn = recconn->next; - } - } - if (recdata->mem_ctx) { - talloc_destroy(recdata->mem_ctx); - } - recdata = NULL; - } -} - -static int recycle_connect(struct tcon_context *conn, const char *service, const char *user) -{ - TALLOC_CTX *ctx = NULL; - recycle_bin_struct *recbin; - recycle_bin_connections *recconn; - recycle_bin_connections *recconnbase; - recycle_bin_private_data *recdata; - char *tmp_str; - - DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user)); - - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return -1; - } - - if (!(ctx = talloc_init("recycle bin connection"))) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return -1; - } - - recbin = talloc(ctx, sizeof(recycle_bin_struct)); - if (recbin == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return -1; - } - recbin->mem_ctx = ctx; - - /* Set defaults */ - recbin->repository = talloc_strdup(recbin->mem_ctx, ".recycle"); - ALLOC_CHECK(recbin->repository, error); - recbin->keep_dir_tree = False; - recbin->versions = False; - recbin->touch = False; - recbin->exclude = ""; - recbin->exclude_dir = ""; - recbin->noversions = ""; - recbin->maxsize = 0; - - /* parse configuration options */ - if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "repository")) != NULL) { - recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str); - ALLOC_CHECK(recbin->repository, error); - trim_string(recbin->repository, "/", "/"); - DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository)); - } - - recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree", False); - DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree)); - - recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions", False); - DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions)); - - recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch", False); - DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch)); - - recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize"); - if (recbin->maxsize == 0) { - recbin->maxsize = -1; - DEBUG(5, ("recycle.bin: maxsize = -infinite-\n")); - } else { - DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); - } - - if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude")) != NULL) { - recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->exclude, error); - DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude)); - } - if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir")) != NULL) { - recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->exclude_dir, error); - DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir)); - } - if ((tmp_str = lp_parm_string(SNUM(conn), "vfs_recycle_bin", "noversions")) != NULL) { - recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->noversions, error); - DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions)); - } - - recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections)); - if (recconn == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - goto error; - } - recconn->conn = SNUM(conn); - recconn->data = recbin; - recconn->next = NULL; - if (recdata->conns) { - recconnbase = recdata->conns; - while (recconnbase->next != NULL) recconnbase = recconnbase->next; - recconnbase->next = recconn; - } else { - recdata->conns = recconn; - } - return default_vfs_ops.connect(conn, service, user); - -error: - talloc_destroy(ctx); - return -1; -} - -static void recycle_disconnect(struct tcon_context *conn) -{ - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; - - DEBUG(10, ("Disconnecting VFS module recycle bin\n")); - - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return; - } - - if (recdata) { - if (recdata->conns) { - if (recdata->conns->conn == SNUM(conn)) { - talloc_destroy(recdata->conns->data->mem_ctx); - recdata->conns = recdata->conns->next; - } else { - recconn = recdata->conns; - while (recconn->next) { - if (recconn->next->conn == SNUM(conn)) { - talloc_destroy(recconn->next->data->mem_ctx); - recconn->next = recconn->next->next; - break; - } - recconn = recconn->next; - } - } - } - } - default_vfs_ops.disconnect(conn); -} - -static BOOL recycle_directory_exist(struct tcon_context *conn, const char *dname) -{ - SMB_STRUCT_STAT st; - - if (default_vfs_ops.stat(conn, dname, &st) == 0) { - if (S_ISDIR(st.st_mode)) { - return True; - } - } - - return False; -} - -static BOOL recycle_file_exist(struct tcon_context *conn, const char *fname) -{ - SMB_STRUCT_STAT st; - - if (default_vfs_ops.stat(conn, fname, &st) == 0) { - if (S_ISREG(st.st_mode)) { - return True; - } - } - - return False; -} - -/** - * Return file size - * @param conn connection - * @param fname file name - * @return size in bytes - **/ -static SMB_OFF_T recycle_get_file_size(struct tcon_context *conn, const char *fname) -{ - SMB_STRUCT_STAT st; - if (default_vfs_ops.stat(conn, fname, &st) != 0) { - DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); - return (SMB_OFF_T)0; - } - return(st.st_size); -} - -/** - * Create directory tree - * @param conn connection - * @param dname Directory tree to be created - * @return Returns True for success - **/ -static BOOL recycle_create_dir(struct tcon_context *conn, const char *dname) -{ - int len; - mode_t mode; - char *new_dir = NULL; - char *tmp_str = NULL; - char *token; - char *tok_str; - BOOL ret = False; - - mode = S_IREAD | S_IWRITE | S_IEXEC; - - tmp_str = strdup(dname); - ALLOC_CHECK(tmp_str, done); - tok_str = tmp_str; - - len = strlen(dname); - new_dir = (char *)malloc(len + 1); - ALLOC_CHECK(new_dir, done); - *new_dir = '\0'; - - /* Create directory tree if neccessary */ - for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) { - safe_strcat(new_dir, token, len); - if (recycle_directory_exist(conn, new_dir)) - DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir)); - else { - DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir)); - if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) { - DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno))); - ret = False; - goto done; - } - } - safe_strcat(new_dir, "/", len); - } - - ret = True; -done: - SAFE_FREE(tmp_str); - SAFE_FREE(new_dir); - return ret; -} - -/** - * Check if needle is contained exactly in haystack - * @param haystack list of parameters separated by delimimiter character - * @param needle string to be matched exactly to haystack - * @return True if found - **/ -static BOOL checkparam(const char *haystack, const char *needle) -{ - char *token; - char *tok_str; - char *tmp_str; - BOOL ret = False; - - if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { - return False; - } - - tmp_str = strdup(haystack); - ALLOC_CHECK(tmp_str, done); - token = tok_str = tmp_str; - - for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { - if(strcmp(token, needle) == 0) { - ret = True; - goto done; - } - } -done: - SAFE_FREE(tmp_str); - return ret; -} - -/** - * Check if needle is contained in haystack, * and ? patterns are resolved - * @param haystack list of parameters separated by delimimiter character - * @param needle string to be matched exectly to haystack including pattern matching - * @return True if found - **/ -static BOOL matchparam(const char *haystack, const char *needle) -{ - char *token; - char *tok_str; - char *tmp_str; - BOOL ret = False; - - if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { - return False; - } - - tmp_str = strdup(haystack); - ALLOC_CHECK(tmp_str, done); - token = tok_str = tmp_str; - - for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { - if (!unix_wild_match(token, needle)) { - ret = True; - goto done; - } - } -done: - SAFE_FREE(tmp_str); - return ret; -} - -/** - * Touch access date - **/ -static void recycle_touch(struct tcon_context *conn, const char *fname) -{ - SMB_STRUCT_STAT st; - struct utimbuf tb; - time_t currtime; - - if (default_vfs_ops.stat(conn, fname, &st) != 0) { - DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); - return; - } - currtime = time(&currtime); - tb.actime = currtime; - tb.modtime = st.st_mtime; - - if (default_vfs_ops.utime(conn, fname, &tb) == -1 ) - DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno))); - } - -/** - * Check if file should be recycled - **/ -static int recycle_unlink(struct tcon_context *conn, const char *file_name) -{ - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; - recycle_bin_struct *recbin; - char *path_name = NULL; - char *temp_name = NULL; - char *final_name = NULL; - const char *base; - int i; -/* SMB_BIG_UINT dfree, dsize, bsize; */ - SMB_OFF_T file_size; /* space_avail; */ - BOOL exist; - int rc = -1; - - recbin = NULL; - if (recycle_bin_private_handle) { - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - if (recdata) { - if (recdata->conns) { - recconn = recdata->conns; - while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next; - if (recconn != NULL) { - recbin = recconn->data; - } - } - } - } - if (recbin == NULL) { - DEBUG(0, ("Recycle bin not initialized!\n")); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - if(!recbin->repository || *(recbin->repository) == '\0') { - DEBUG(3, ("Recycle path not set, purging %s...\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - /* we don't recycle the recycle bin... */ - if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) { - DEBUG(3, ("File is within recycling bin, unlinking ...\n")); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - file_size = recycle_get_file_size(conn, file_name); - /* it is wrong to purge filenames only because they are empty imho - * --- simo - * - if(fsize == 0) { - DEBUG(3, ("File %s is empty, purging...\n", file_name)); - rc = default_vfs_ops.unlink(conn,file_name); - goto done; - } - */ - - /* FIXME: this is wrong, we should check the hole size of the recycle bin is - * not greater then maxsize, not the size of the single file, also it is better - * to remove older files - */ - if(recbin->maxsize > 0 && file_size > recbin->maxsize) { - DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - /* FIXME: this is wrong: moving files with rename does not change the disk space - * allocation - * - space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L; - DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); - if(space_avail < file_size) { - DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - */ - - /* extract filename and path */ - path_name = (char *)malloc(PATH_MAX); - ALLOC_CHECK(path_name, done); - *path_name = '\0'; - safe_strcpy(path_name, file_name, PATH_MAX - 1); - base = strrchr(path_name, '/'); - if (base == NULL) { - base = file_name; - safe_strcpy(path_name, "/", PATH_MAX - 1); - } - else { - base++; - } - - DEBUG(10, ("recycle.bin: fname = %s\n", file_name)); /* original filename with path */ - DEBUG(10, ("recycle.bin: fpath = %s\n", path_name)); /* original path */ - DEBUG(10, ("recycle.bin: base = %s\n", base)); /* filename without path */ - - if (matchparam(recbin->exclude, base)) { - DEBUG(3, ("recycle.bin: file %s is excluded \n", base)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - /* FIXME: this check will fail if we have more than one level of directories, - * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... - * ---simo - */ - if (checkparam(recbin->exclude_dir, path_name)) { - DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - temp_name = (char *)strdup(recbin->repository); - ALLOC_CHECK(temp_name, done); - - /* see if we need to recreate the original directory structure in the recycle bin */ - if (recbin->keep_dir_tree == True) { - safe_strcat(temp_name, "/", PATH_MAX - 1); - safe_strcat(temp_name, path_name, PATH_MAX - 1); - } - - exist = recycle_directory_exist(conn, temp_name); - if (exist) { - DEBUG(10, ("recycle.bin: Directory already exists\n")); - } else { - DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name)); - if (recycle_create_dir(conn, temp_name) == False) { - DEBUG(3, ("Could not create directory, purging %s...\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - } - - final_name = NULL; - asprintf(&final_name, "%s/%s", temp_name, base); - ALLOC_CHECK(final_name, done); - DEBUG(10, ("recycle.bin: recycled file name%s\n", temp_name)); /* new filename with path */ - - /* check if we should delete file from recycle bin */ - if (recycle_file_exist(conn, final_name)) { - if (recbin->versions == False || matchparam(recbin->noversions, base) == True) { - DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name)); - if (default_vfs_ops.unlink(conn, final_name) != 0) { - DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno))); - } - } - } - - /* rename file we move to recycle bin */ - i = 1; - while (recycle_file_exist(conn, final_name)) { - snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base); - } - - DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name)); - rc = default_vfs_ops.rename(conn, file_name, final_name); - if (rc != 0) { - DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - /* touch access date of moved file */ - if (recbin->touch == True ) - recycle_touch(conn, final_name); - -done: - SAFE_FREE(path_name); - SAFE_FREE(temp_name); - SAFE_FREE(final_name); - return rc; -} diff --git a/source4/modules/xml.c b/source4/modules/xml.c deleted file mode 100644 index ead3e3a874..0000000000 --- a/source4/modules/xml.c +++ /dev/null @@ -1,575 +0,0 @@ - -/* - * XML password backend for samba - * Copyright (C) Jelmer Vernooij 2002 - * Some parts based on the libxml gjobread example by Daniel Veillard - * - * 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. - */ - -/* FIXME: - * - Support stdin input by using '-' - * - Be faster. Don't rewrite the whole file when adding a user, but store it in the memory and save it when exiting. Requires changes to samba source. - * - Gives the ability to read/write to standard input/output - * - Do locking! - * - Better names! - */ - - -#define XML_URL "http://www.samba.org/ns" - -#include "includes.h" - -#include <libxml/xmlmemory.h> -#include <libxml/parser.h> - -static int xmlsam_debug_level = DBGC_ALL; - -#undef DBGC_CLASS -#define DBGC_CLASS xmlsam_debug_level - -static char * iota(int a) { - static char tmp[10]; - - snprintf(tmp, 9, "%d", a); - return tmp; -} - -BOOL parsePass(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, SAM_ACCOUNT * u) -{ - pstring temp; - - cur = cur->xmlChildrenNode; - while (cur != NULL) { - if (strcmp(cur->name, "crypt")) - DEBUG(0, ("Unknown element %s\n", cur->name)); - else { - if (!strcmp(xmlGetProp(cur, "type"), "nt") - && - pdb_gethexpwd(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1), temp)) - pdb_set_nt_passwd(u, temp, PDB_SET); - else if (!strcmp(xmlGetProp(cur, "type"), "lanman") - && - pdb_gethexpwd(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1), temp)) - pdb_set_lanman_passwd(u, temp, PDB_SET); - else - DEBUG(0, - ("Unknown crypt type: %s\n", - xmlGetProp(cur, "type"))); - } - cur = cur->next; - } - return True; -} - -BOOL parseUser(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, SAM_ACCOUNT * u) -{ - char *tmp; - DOM_SID sid; - - tmp = xmlGetProp(cur, "sid"); - if (tmp){ - string_to_sid(&sid, tmp); - pdb_set_user_sid(u, &sid, PDB_SET); - } - tmp = xmlGetProp(cur, "uid"); - if (tmp) - pdb_set_uid(u, atol(tmp), PDB_SET); - pdb_set_username(u, xmlGetProp(cur, "name"), PDB_SET); - /* We don't care what the top level element name is */ - cur = cur->xmlChildrenNode; - while (cur != NULL) { - if ((!strcmp(cur->name, "group")) && (cur->ns == ns)) { - tmp = xmlGetProp(cur, "gid"); - if (tmp) - pdb_set_gid(u, atol(tmp), PDB_SET); - tmp = xmlGetProp(cur, "sid"); - if (tmp){ - string_to_sid(&sid, tmp); - pdb_set_group_sid(u, &sid, PDB_SET); - } - } - - else if ((!strcmp(cur->name, "domain")) && (cur->ns == ns)) - pdb_set_domain(u, - xmlNodeListGetString(doc, cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "fullname") && cur->ns == ns) - pdb_set_fullname(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "nt_username") && cur->ns == ns) - pdb_set_nt_username(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "logon_script") && cur->ns == ns) - pdb_set_logon_script(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "profile_path") && cur->ns == ns) - pdb_set_profile_path(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "logon_time") && cur->ns == ns) - pdb_set_logon_time(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "logoff_time") && cur->ns == ns) - pdb_set_logoff_time(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), - PDB_SET); - - else if (!strcmp(cur->name, "kickoff_time") && cur->ns == ns) - pdb_set_kickoff_time(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), - PDB_SET); - - else if (!strcmp(cur->name, "logon_divs") && cur->ns == ns) - pdb_set_logon_divs(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "hours_len") && cur->ns == ns) - pdb_set_hours_len(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "unknown_3") && cur->ns == ns) - pdb_set_unknown_3(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "unknown_5") && cur->ns == ns) - pdb_set_unknown_5(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "unknown_6") && cur->ns == ns) - pdb_set_unknown_6(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "homedir") && cur->ns == ns) - pdb_set_homedir(u, - xmlNodeListGetString(doc, cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "unknown_str") && cur->ns == ns) - pdb_set_unknown_str(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "dir_drive") && cur->ns == ns) - pdb_set_dir_drive(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "munged_dial") && cur->ns == ns) - pdb_set_munged_dial(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "acct_desc") && cur->ns == ns) - pdb_set_acct_desc(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if (!strcmp(cur->name, "acct_ctrl") && cur->ns == ns) - pdb_set_acct_ctrl(u, - atol(xmlNodeListGetString - (doc, cur->xmlChildrenNode, 1)), PDB_SET); - - else if (!strcmp(cur->name, "workstations") && cur->ns == ns) - pdb_set_workstations(u, - xmlNodeListGetString(doc, - cur->xmlChildrenNode, - 1), PDB_SET); - - else if ((!strcmp(cur->name, "password")) && (cur->ns == ns)) { - tmp = xmlGetProp(cur, "last_set"); - if (tmp) - pdb_set_pass_last_set_time(u, atol(tmp), PDB_SET); - tmp = xmlGetProp(cur, "must_change"); - if (tmp) - pdb_set_pass_must_change_time(u, atol(tmp), PDB_SET); - tmp = xmlGetProp(cur, "can_change"); - if (tmp) - pdb_set_pass_can_change_time(u, atol(tmp), PDB_SET); - parsePass(doc, ns, cur, u); - } - - else - DEBUG(0, ("Unknown element %s\n", cur->name)); - cur = cur->next; - } - - return True; -} - -typedef struct pdb_xml { - char *location; - char written; - xmlDocPtr doc; - xmlNodePtr users; - xmlNodePtr pwent; - xmlNsPtr ns; -} pdb_xml; - -xmlNodePtr parseSambaXMLFile(struct pdb_xml *data) -{ - xmlNodePtr cur; - - data->doc = xmlParseFile(data->location); - if (data->doc == NULL) - return NULL; - - cur = xmlDocGetRootElement(data->doc); - if (!cur) { - DEBUG(0, ("empty document\n")); - xmlFreeDoc(data->doc); - return NULL; - } - data->ns = xmlSearchNsByHref(data->doc, cur, XML_URL); - if (!data->ns) { - DEBUG(0, - ("document of the wrong type, samba user namespace not found\n")); - xmlFreeDoc(data->doc); - return NULL; - } - if (strcmp(cur->name, "samba")) { - DEBUG(0, ("document of the wrong type, root node != samba")); - xmlFreeDoc(data->doc); - return NULL; - } - - cur = cur->xmlChildrenNode; - while (cur && xmlIsBlankNode(cur)) { - cur = cur->next; - } - if (!cur) - return NULL; - if ((strcmp(cur->name, "users")) || (cur->ns != data->ns)) { - DEBUG(0, ("document of the wrong type, was '%s', users expected", - cur->name)); - DEBUG(0, ("xmlDocDump follows\n")); - xmlDocDump(stderr, data->doc); - DEBUG(0, ("xmlDocDump finished\n")); - xmlFreeDoc(data->doc); - return NULL; - } - data->users = cur; - cur = cur->xmlChildrenNode; - return cur; -} - -static NTSTATUS xmlsam_setsampwent(struct pdb_methods *methods, BOOL update) -{ - pdb_xml *data; - - if (!methods) { - DEBUG(0, ("Invalid methods\n")); - return NT_STATUS_INVALID_PARAMETER; - } - data = (pdb_xml *) methods->private_data; - if (!data) { - DEBUG(0, ("Invalid pdb_xml_data\n")); - return NT_STATUS_INVALID_PARAMETER; - } - data->pwent = parseSambaXMLFile(data); - if (!data->pwent) - return NT_STATUS_UNSUCCESSFUL; - - return NT_STATUS_OK; -} - -/*************************************************************** - End enumeration of the passwd list. - ****************************************************************/ - -static void xmlsam_endsampwent(struct pdb_methods *methods) -{ - pdb_xml *data; - - if (!methods) { - DEBUG(0, ("Invalid methods\n")); - return; - } - - data = (pdb_xml *) methods->private_data; - - if (!data) { - DEBUG(0, ("Invalid pdb_xml_data\n")); - return; - } - - xmlFreeDoc(data->doc); - data->doc = NULL; - data->pwent = NULL; -} - -/***************************************************************** - Get one SAM_ACCOUNT from the list (next in line) - *****************************************************************/ - -static NTSTATUS xmlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user) -{ - pdb_xml *data; - - if (!methods) { - DEBUG(0, ("Invalid methods\n")); - return NT_STATUS_INVALID_PARAMETER; - } - data = (pdb_xml *) methods->private_data; - - if (!data) { - DEBUG(0, ("Invalid pdb_xml_data\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - while (data->pwent) { - if ((!strcmp(data->pwent->name, "user")) && - (data->pwent->ns == data->ns)) { - - parseUser(data->doc, data->ns, data->pwent, user); - data->pwent = data->pwent->next; - return NT_STATUS_OK; - } - data->pwent = data->pwent->next; - } - return NT_STATUS_UNSUCCESSFUL; -} - -/*************************************************************************** - Adds an existing SAM_ACCOUNT - ****************************************************************************/ - -static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * u) -{ - pstring temp; - fstring sid_str; - xmlNodePtr cur, user, pass, root; - pdb_xml *data; - - DEBUG(10, ("xmlsam_add_sam_account called!\n")); - - if (!methods) { - DEBUG(0, ("Invalid methods\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - data = (pdb_xml *) methods->private_data; - if (!data) { - DEBUG(0, ("Invalid pdb_xml_data\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - /* Create a new document if we can't open the current one */ - if (!parseSambaXMLFile(data)) { - DEBUG(0, ("Can't load current XML file, creating a new one\n")); - data->doc = xmlNewDoc(XML_DEFAULT_VERSION); - root = xmlNewDocNode(data->doc, NULL, "samba", NULL); - cur = xmlDocSetRootElement(data->doc, root); - data->ns = xmlNewNs(root, XML_URL, "samba"); - data->users = xmlNewChild(root, data->ns, "users", NULL); - } - - user = xmlNewChild(data->users, data->ns, "user", NULL); - xmlNewProp(user, "sid", - sid_to_string(sid_str, pdb_get_user_sid(u))); - if (pdb_get_init_flags(u, PDB_UID) != PDB_DEFAULT) - xmlNewProp(user, "uid", iota(pdb_get_uid(u))); - - if (pdb_get_username(u) && strcmp(pdb_get_username(u), "")) - xmlNewProp(user, "name", pdb_get_username(u)); - - cur = xmlNewChild(user, data->ns, "group", NULL); - - xmlNewProp(cur, "sid", - sid_to_string(sid_str, pdb_get_group_sid(u))); - if (pdb_get_init_flags(u, PDB_GID) != PDB_DEFAULT) - xmlNewProp(cur, "gid", iota(pdb_get_gid(u))); - - if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT) - xmlNewChild(user, data->ns, "login_time", - iota(pdb_get_logon_time(u))); - - if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT) - xmlNewChild(user, data->ns, "logoff_time", - iota(pdb_get_logoff_time(u))); - - if (pdb_get_init_flags(u, PDB_KICKOFFTIME) != PDB_DEFAULT) - xmlNewChild(user, data->ns, "kickoff_time", - iota(pdb_get_kickoff_time(u))); - - if (pdb_get_domain(u) && strcmp(pdb_get_domain(u), "")) - xmlNewChild(user, data->ns, "domain", pdb_get_domain(u)); - - if (pdb_get_nt_username(u) && strcmp(pdb_get_nt_username(u), "")) - xmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u)); - - if (pdb_get_fullname(u) && strcmp(pdb_get_fullname(u), "")) - xmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u)); - - if (pdb_get_homedir(u) && strcmp(pdb_get_homedir(u), "")) - xmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u)); - - if (pdb_get_dir_drive(u) && strcmp(pdb_get_dir_drive(u), "")) - xmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u)); - - if (pdb_get_logon_script(u) && strcmp(pdb_get_logon_script(u), "")) - xmlNewChild(user, data->ns, "logon_script", - pdb_get_logon_script(u)); - - if (pdb_get_profile_path(u) && strcmp(pdb_get_profile_path(u), "")) - xmlNewChild(user, data->ns, "profile_path", - pdb_get_profile_path(u)); - - if (pdb_get_acct_desc(u) && strcmp(pdb_get_acct_desc(u), "")) - xmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u)); - - if (pdb_get_workstations(u) && strcmp(pdb_get_workstations(u), "")) - xmlNewChild(user, data->ns, "workstations", - pdb_get_workstations(u)); - - if (pdb_get_unknown_str(u) && strcmp(pdb_get_unknown_str(u), "")) - xmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u)); - - if (pdb_get_munged_dial(u) && strcmp(pdb_get_munged_dial(u), "")) - xmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u)); - - - /* Password stuff */ - pass = xmlNewChild(user, data->ns, "password", NULL); - if (pdb_get_pass_last_set_time(u)) - xmlNewProp(pass, "last_set", iota(pdb_get_pass_last_set_time(u))); - if (pdb_get_init_flags(u, PDB_CANCHANGETIME) != PDB_DEFAULT) - xmlNewProp(pass, "can_change", - iota(pdb_get_pass_can_change_time(u))); - - if (pdb_get_init_flags(u, PDB_MUSTCHANGETIME) != PDB_DEFAULT) - xmlNewProp(pass, "must_change", - iota(pdb_get_pass_must_change_time(u))); - - - if (pdb_get_lanman_passwd(u)) { - pdb_sethexpwd(temp, pdb_get_lanman_passwd(u), - pdb_get_acct_ctrl(u)); - cur = xmlNewChild(pass, data->ns, "crypt", temp); - xmlNewProp(cur, "type", "lanman"); - } - - if (pdb_get_nt_passwd(u)) { - pdb_sethexpwd(temp, pdb_get_nt_passwd(u), pdb_get_acct_ctrl(u)); - cur = xmlNewChild(pass, data->ns, "crypt", temp); - xmlNewProp(cur, "type", "nt"); - } - - xmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u))); - xmlNewChild(user, data->ns, "unknown_3", iota(pdb_get_unknown_3(u))); - - if (pdb_get_logon_divs(u)) - xmlNewChild(user, data->ns, "logon_divs", - iota(pdb_get_logon_divs(u))); - - if (pdb_get_hours_len(u)) - xmlNewChild(user, data->ns, "hours_len", - iota(pdb_get_hours_len(u))); - - xmlNewChild(user, data->ns, "unknown_5", iota(pdb_get_unknown_5(u))); - xmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u))); - xmlSaveFile(data->location, data->doc); - - return NT_STATUS_OK; -} - -NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method, - const char *location) -{ - NTSTATUS nt_status; - pdb_xml *data; - - xmlsam_debug_level = debug_add_class("xmlsam"); - if (xmlsam_debug_level == -1) { - xmlsam_debug_level = DBGC_ALL; - DEBUG(0, ("xmlsam: Couldn't register custom debugging class!\n")); - } - - if (!pdb_context) { - DEBUG(0, ("invalid pdb_methods specified\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!NT_STATUS_IS_OK - (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { - return nt_status; - } - - (*pdb_method)->name = "xmlsam"; - - (*pdb_method)->setsampwent = xmlsam_setsampwent; - (*pdb_method)->endsampwent = xmlsam_endsampwent; - (*pdb_method)->getsampwent = xmlsam_getsampwent; - (*pdb_method)->add_sam_account = xmlsam_add_sam_account; - (*pdb_method)->getsampwnam = NULL; - (*pdb_method)->getsampwsid = NULL; - (*pdb_method)->update_sam_account = NULL; - (*pdb_method)->delete_sam_account = NULL; - (*pdb_method)->getgrsid = NULL; - (*pdb_method)->getgrgid = NULL; - (*pdb_method)->getgrnam = NULL; - (*pdb_method)->add_group_mapping_entry = NULL; - (*pdb_method)->update_group_mapping_entry = NULL; - (*pdb_method)->delete_group_mapping_entry = NULL; - (*pdb_method)->enum_group_mapping = NULL; - - data = talloc(pdb_context->mem_ctx, sizeof(pdb_xml)); - data->location = - (location ? talloc_strdup(pdb_context->mem_ctx, location) : "-"); - data->pwent = NULL; - data->written = 0; - (*pdb_method)->private_data = data; - - LIBXML_TEST_VERSION xmlKeepBlanksDefault(0); - - return NT_STATUS_OK; -} - -int init_module(void); - -int init_module() -{ - if(smb_register_passdb("xml", xmlsam_init, PASSDB_INTERFACE_VERSION)) - return 0; - - return 1; -} diff --git a/source4/nmbd/asyncdns.c b/source4/nmbd/asyncdns.c deleted file mode 100644 index c86ee69a09..0000000000 --- a/source4/nmbd/asyncdns.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - Unix SMB/CIFS implementation. - a async DNS handler - Copyright (C) Andrew Tridgell 1997-1998 - - 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" - -/*************************************************************************** - Add a DNS result to the name cache. -****************************************************************************/ - -static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr) -{ - int name_type = question->name_type; - char *qname = question->name; - - - if (!addr.s_addr) { - /* add the fail to WINS cache of names. give it 1 hour in the cache */ - DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); - (void)add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); - return( NULL ); - } - - /* add it to our WINS cache of names. give it 2 hours in the cache */ - DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); - - return( add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); -} - - - -#ifndef SYNC_DNS - -static int fd_in = -1, fd_out = -1; -static pid_t child_pid = -1; -static int in_dns; - -/* this is the structure that is passed between the parent and child */ -struct query_record { - struct nmb_name name; - struct in_addr result; -}; - -/* a queue of pending requests waiting to be sent to the DNS child */ -static struct packet_struct *dns_queue; - -/* the packet currently being processed by the dns child */ -static struct packet_struct *dns_current; - - -/*************************************************************************** - return the fd used to gather async dns replies. This is added to the select - loop - ****************************************************************************/ -int asyncdns_fd(void) -{ - return fd_in; -} - -/*************************************************************************** - handle DNS queries arriving from the parent - ****************************************************************************/ -static void asyncdns_process(void) -{ - struct query_record r; - fstring qname; - - DEBUGLEVEL = -1; - - while (1) { - if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r)) - break; - - fstrcpy(qname, r.name.name); - - r.result.s_addr = interpret_addr(qname); - - if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r)) - break; - } - - _exit(0); -} - -/**************************************************************************** ** - catch a sigterm (in the child process - the parent has a different handler - see nmbd.c for details). - We need a separate term handler here so we don't release any - names that our parent is going to release, or overwrite a - WINS db that our parent is going to write. - **************************************************************************** */ - -static void sig_term(int sig) -{ - _exit(0); -} - -/*************************************************************************** - Called by the parent process when it receives a SIGTERM - also kills the - child so we don't get child async dns processes lying around, causing trouble. - ****************************************************************************/ - -void kill_async_dns_child(void) -{ - if (child_pid > 0) { - kill(child_pid, SIGTERM); - child_pid = -1; - } -} - -/*************************************************************************** - create a child process to handle DNS lookups - ****************************************************************************/ -void start_async_dns(void) -{ - int fd1[2], fd2[2]; - - CatchChild(); - - if (pipe(fd1) || pipe(fd2)) { - DEBUG(0,("can't create asyncdns pipes\n")); - return; - } - - child_pid = sys_fork(); - - if (child_pid) { - fd_in = fd1[0]; - fd_out = fd2[1]; - close(fd1[1]); - close(fd2[0]); - DEBUG(0,("started asyncdns process %d\n", (int)child_pid)); - return; - } - - fd_in = fd2[0]; - fd_out = fd1[1]; - - CatchSignal(SIGUSR2, SIG_IGN); - CatchSignal(SIGUSR1, SIG_IGN); - CatchSignal(SIGHUP, SIG_IGN); - CatchSignal(SIGTERM, SIGNAL_CAST sig_term ); - - asyncdns_process(); -} - - -/*************************************************************************** -check if a particular name is already being queried - ****************************************************************************/ -static BOOL query_current(struct query_record *r) -{ - return dns_current && - nmb_name_equal(&r->name, - &dns_current->packet.nmb.question.question_name); -} - - -/*************************************************************************** - write a query to the child process - ****************************************************************************/ -static BOOL write_child(struct packet_struct *p) -{ - struct query_record r; - - r.name = p->packet.nmb.question.question_name; - - return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r); -} - -/*************************************************************************** - check the DNS queue - ****************************************************************************/ -void run_dns_queue(void) -{ - struct query_record r; - struct packet_struct *p, *p2; - struct name_record *namerec; - int size; - - if (fd_in == -1) - return; - - /* Allow SIGTERM to kill us. */ - BlockSignals(False, SIGTERM); - - if (!process_exists(child_pid)) { - close(fd_in); - start_async_dns(); - } - - if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) { - if (size) { - DEBUG(0,("Incomplete DNS answer from child!\n")); - fd_in = -1; - } - BlockSignals(True, SIGTERM); - return; - } - - BlockSignals(True, SIGTERM); - - namerec = add_dns_result(&r.name, r.result); - - if (dns_current) { - if (query_current(&r)) { - DEBUG(3,("DNS calling send_wins_name_query_response\n")); - in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, dns_current, NULL); - else - send_wins_name_query_response(0,dns_current,namerec); - in_dns = 0; - } - - dns_current->locked = False; - free_packet(dns_current); - dns_current = NULL; - } - - /* loop over the whole dns queue looking for entries that - match the result we just got */ - for (p = dns_queue; p;) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - - if (nmb_name_equal(question, &r.name)) { - DEBUG(3,("DNS calling send_wins_name_query_response\n")); - in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0,p,namerec); - in_dns = 0; - p->locked = False; - - if (p->prev) - p->prev->next = p->next; - else - dns_queue = p->next; - if (p->next) - p->next->prev = p->prev; - p2 = p->next; - free_packet(p); - p = p2; - } else { - p = p->next; - } - } - - if (dns_queue) { - dns_current = dns_queue; - dns_queue = dns_queue->next; - if (dns_queue) dns_queue->prev = NULL; - dns_current->next = NULL; - - if (!write_child(dns_current)) { - DEBUG(3,("failed to send DNS query to child!\n")); - return; - } - } - -} - -/*************************************************************************** -queue a DNS query - ****************************************************************************/ -BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, - struct name_record **n) -{ - if (in_dns || fd_in == -1) - return False; - - if (!dns_current) { - if (!write_child(p)) { - DEBUG(3,("failed to send DNS query to child!\n")); - return False; - } - dns_current = p; - p->locked = True; - } else { - p->locked = True; - p->next = dns_queue; - p->prev = NULL; - if (p->next) - p->next->prev = p; - dns_queue = p; - } - - DEBUG(3,("added DNS query for %s\n", nmb_namestr(question))); - return True; -} - -#else - - -/*************************************************************************** - we use this when we can't do async DNS lookups - ****************************************************************************/ -BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, - struct name_record **n) -{ - char *qname = question->name; - struct in_addr dns_ip; - - DEBUG(3,("DNS search for %s - ", nmb_namestr(question))); - - /* Unblock TERM signal so we can be killed in DNS lookup. */ - BlockSignals(False, SIGTERM); - - dns_ip.s_addr = interpret_addr(qname); - - /* Re-block TERM signal. */ - BlockSignals(True, SIGTERM); - - *n = add_dns_result(question, dns_ip); - if(*n == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0, p, *n); - return False; -} - -/*************************************************************************** - With sync dns there is no child to kill on SIGTERM. - ****************************************************************************/ -void kill_async_dns_child(void) -{ - return; -} -#endif diff --git a/source4/nmbd/nmbd.c b/source4/nmbd/nmbd.c deleted file mode 100644 index 0fa3525666..0000000000 --- a/source4/nmbd/nmbd.c +++ /dev/null @@ -1,778 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Jeremy Allison 1997-2002 - Copyright (C) Jelmer Vernooij 2002 (Conversion to popt) - - 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" - -int ClientNMB = -1; -int ClientDGRAM = -1; -int global_nmb_port = -1; - -extern BOOL global_in_nmbd; - -/* are we running as a daemon ? */ -static BOOL is_daemon = False; - -/* fork or run in foreground ? */ -static BOOL Fork = True; - -/* log to standard output ? */ -static BOOL log_stdout = False; - -/* have we found LanMan clients yet? */ -BOOL found_lm_clients = False; - -/* what server type are we currently */ - -time_t StartupTime = 0; - -/**************************************************************************** ** - Handle a SIGTERM in band. - **************************************************************************** */ - -static void terminate(void) -{ - DEBUG(0,("Got SIGTERM: going down...\n")); - - /* Write out wins.dat file if samba is a WINS server */ - wins_write_database(False); - - /* Remove all SELF registered names from WINS */ - release_wins_names(); - - /* Announce all server entries as 0 time-to-live, 0 type. */ - announce_my_servers_removed(); - - /* If there was an async dns child - kill it. */ - kill_async_dns_child(); - - exit(0); -} - -/**************************************************************************** ** - Handle a SHUTDOWN message from smbcontrol. - **************************************************************************** */ - -static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len) -{ - terminate(); -} - -/**************************************************************************** ** - Catch a SIGTERM signal. - **************************************************************************** */ - -static sig_atomic_t got_sig_term; - -static void sig_term(int sig) -{ - got_sig_term = 1; - sys_select_signal(); -} - -/**************************************************************************** ** - Catch a SIGHUP signal. - **************************************************************************** */ - -static sig_atomic_t reload_after_sighup; - -static void sig_hup(int sig) -{ - reload_after_sighup = 1; - sys_select_signal(); -} - -/******************************************************************* - Print out all talloc memory info. -********************************************************************/ - -void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len) -{ - TALLOC_CTX *ctx = talloc_init("info context"); - char *info = NULL; - - if (!ctx) - return; - - info = talloc_describe_all(ctx); - if (info) - DEBUG(10,(info)); - message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1 : 0, True); - talloc_destroy(ctx); -} - -#if DUMP_CORE -/**************************************************************************** ** - Prepare to dump a core file - carefully! - **************************************************************************** */ - -static BOOL dump_core(void) -{ - char *p; - pstring dname; - pstrcpy( dname, lp_logfile() ); - if ((p=strrchr_m(dname,'/'))) - *p=0; - pstrcat( dname, "/corefiles" ); - mkdir( dname, 0700 ); - sys_chown( dname, getuid(), getgid() ); - chmod( dname, 0700 ); - if ( chdir(dname) ) - return( False ); - umask( ~(0700) ); - -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit( RLIMIT_CORE, &rlp ); - rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur ); - setrlimit( RLIMIT_CORE, &rlp ); - getrlimit( RLIMIT_CORE, &rlp ); - DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) ); - } -#endif -#endif - - - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return( True ); -} -#endif - -/**************************************************************************** ** - Possibly continue after a fault. - **************************************************************************** */ - -static void fault_continue(void) -{ -#if DUMP_CORE - dump_core(); -#endif -} - -/**************************************************************************** ** - Expire old names from the namelist and server list. - **************************************************************************** */ - -static void expire_names_and_servers(time_t t) -{ - static time_t lastrun = 0; - - if ( !lastrun ) - lastrun = t; - if ( t < (lastrun + 5) ) - return; - lastrun = t; - - /* - * Expire any timed out names on all the broadcast - * subnets and those registered with the WINS server. - * (nmbd_namelistdb.c) - */ - - expire_names(t); - - /* - * Go through all the broadcast subnets and for each - * workgroup known on that subnet remove any expired - * server names. If a workgroup has an empty serverlist - * and has itself timed out then remove the workgroup. - * (nmbd_workgroupdb.c) - */ - - expire_workgroups_and_servers(t); -} - -/************************************************************************** ** - Reload the list of network interfaces. - ************************************************************************** */ - -static BOOL reload_interfaces(time_t t) -{ - static time_t lastt; - int n; - struct subnet_record *subrec; - extern BOOL rescan_listen_set; - extern struct in_addr loopback_ip; - - if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False; - lastt = t; - - if (!interfaces_changed()) return False; - - /* the list of probed interfaces has changed, we may need to add/remove - some subnets */ - load_interfaces(); - - /* find any interfaces that need adding */ - for (n=iface_count() - 1; n >= 0; n--) { - struct interface *iface = get_interface(n); - - /* - * We don't want to add a loopback interface, in case - * someone has added 127.0.0.1 for smbd, nmbd needs to - * ignore it here. JRA. - */ - - if (ip_equal(iface->ip, loopback_ip)) { - DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip))); - continue; - } - - for (subrec=subnetlist; subrec; subrec=subrec->next) { - if (ip_equal(iface->ip, subrec->myip) && - ip_equal(iface->nmask, subrec->mask_ip)) break; - } - - if (!subrec) { - /* it wasn't found! add it */ - DEBUG(2,("Found new interface %s\n", - inet_ntoa(iface->ip))); - subrec = make_normal_subnet(iface); - if (subrec) register_my_workgroup_one_subnet(subrec); - } - } - - /* find any interfaces that need deleting */ - for (subrec=subnetlist; subrec; subrec=subrec->next) { - for (n=iface_count() - 1; n >= 0; n--) { - struct interface *iface = get_interface(n); - if (ip_equal(iface->ip, subrec->myip) && - ip_equal(iface->nmask, subrec->mask_ip)) break; - } - if (n == -1) { - /* oops, an interface has disapeared. This is - tricky, we don't dare actually free the - interface as it could be being used, so - instead we just wear the memory leak and - remove it from the list of interfaces without - freeing it */ - DEBUG(2,("Deleting dead interface %s\n", - inet_ntoa(subrec->myip))); - close_subnet(subrec); - } - } - - rescan_listen_set = True; - - /* We need to shutdown if there are no subnets... */ - if (FIRST_SUBNET == NULL) { - DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n")); - return True; - } - return False; -} - -/**************************************************************************** ** - Reload the services file. - **************************************************************************** */ - -static BOOL reload_nmbd_services(BOOL test) -{ - BOOL ret; - - set_remote_machine_name("nmbd"); - - if ( lp_loaded() ) { - pstring fname; - pstrcpy( fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); - test = False; - } - } - - if ( test && !lp_file_list_changed() ) - return(True); - - ret = lp_load( dyn_CONFIGFILE, True , False, False); - - /* perhaps the config filename is now set */ - if ( !test ) { - DEBUG( 3, ( "services not loaded\n" ) ); - reload_nmbd_services( True ); - } - - return(ret); -} - -/**************************************************************************** ** - The main select loop. - **************************************************************************** */ - -static void process(void) -{ - BOOL run_election; - - while( True ) { - time_t t = time(NULL); - - /* Check for internal messages */ - - message_dispatch(); - - /* - * Check all broadcast subnets to see if - * we need to run an election on any of them. - * (nmbd_elections.c) - */ - - run_election = check_elections(); - - /* - * Read incoming UDP packets. - * (nmbd_packets.c) - */ - - if(listen_for_packets(run_election)) - return; - - /* - * Handle termination inband. - */ - - if (got_sig_term) { - got_sig_term = 0; - terminate(); - } - - /* - * Process all incoming packets - * read above. This calls the success and - * failure functions registered when response - * packets arrrive, and also deals with request - * packets from other sources. - * (nmbd_packets.c) - */ - - run_packet_queue(); - - /* - * Run any elections - initiate becoming - * a local master browser if we have won. - * (nmbd_elections.c) - */ - - run_elections(t); - - /* - * Send out any broadcast announcements - * of our server names. This also announces - * the workgroup name if we are a local - * master browser. - * (nmbd_sendannounce.c) - */ - - announce_my_server_names(t); - - /* - * Send out any LanMan broadcast announcements - * of our server names. - * (nmbd_sendannounce.c) - */ - - announce_my_lm_server_names(t); - - /* - * If we are a local master browser, periodically - * announce ourselves to the domain master browser. - * This also deals with syncronising the domain master - * browser server lists with ourselves as a local - * master browser. - * (nmbd_sendannounce.c) - */ - - announce_myself_to_domain_master_browser(t); - - /* - * Fullfill any remote announce requests. - * (nmbd_sendannounce.c) - */ - - announce_remote(t); - - /* - * Fullfill any remote browse sync announce requests. - * (nmbd_sendannounce.c) - */ - - browse_sync_remote(t); - - /* - * Scan the broadcast subnets, and WINS client - * namelists and refresh any that need refreshing. - * (nmbd_mynames.c) - */ - - refresh_my_names(t); - - /* - * Scan the subnet namelists and server lists and - * expire thos that have timed out. - * (nmbd.c) - */ - - expire_names_and_servers(t); - - /* - * Write out a snapshot of our current browse list into - * the browse.dat file. This is used by smbd to service - * incoming NetServerEnum calls - used to synchronise - * browse lists over subnets. - * (nmbd_serverlistdb.c) - */ - - write_browse_list(t, False); - - /* - * If we are a domain master browser, we have a list of - * local master browsers we should synchronise browse - * lists with (these are added by an incoming local - * master browser announcement packet). Expire any of - * these that are no longer current, and pull the server - * lists from each of these known local master browsers. - * (nmbd_browsesync.c) - */ - - dmb_expire_and_sync_browser_lists(t); - - /* - * Check that there is a local master browser for our - * workgroup for all our broadcast subnets. If one - * is not found, start an election (which we ourselves - * may or may not participate in, depending on the - * setting of the 'local master' parameter. - * (nmbd_elections.c) - */ - - check_master_browser_exists(t); - - /* - * If we are configured as a logon server, attempt to - * register the special NetBIOS names to become such - * (WORKGROUP<1c> name) on all broadcast subnets and - * with the WINS server (if used). If we are configured - * to become a domain master browser, attempt to register - * the special NetBIOS name (WORKGROUP<1b> name) to - * become such. - * (nmbd_become_dmb.c) - */ - - add_domain_names(t); - - /* - * If we are a WINS server, do any timer dependent - * processing required. - * (nmbd_winsserver.c) - */ - - initiate_wins_processing(t); - - /* - * If we are a domain master browser, attempt to contact the - * WINS server to get a list of all known WORKGROUPS/DOMAINS. - * This will only work to a Samba WINS server. - * (nmbd_browsesync.c) - */ - - if (lp_enhanced_browsing()) - collect_all_workgroup_names_from_wins_server(t); - - /* - * Go through the response record queue and time out or re-transmit - * and expired entries. - * (nmbd_packets.c) - */ - - retransmit_or_expire_response_records(t); - - /* - * check to see if any remote browse sync child processes have completed - */ - - sync_check_completion(); - - /* - * regularly sync with any other DMBs we know about - */ - - if (lp_enhanced_browsing()) - sync_all_dmbs(t); - - /* - * clear the unexpected packet queue - */ - - clear_unexpected(t); - - /* - * Reload the services file if we got a sighup. - */ - - if(reload_after_sighup) { - DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); - write_browse_list( 0, True ); - dump_all_namelists(); - reload_nmbd_services( True ); - reopen_logs(); - if(reload_interfaces(0)) - return; - reload_after_sighup = 0; - } - - /* check for new network interfaces */ - - if(reload_interfaces(t)) - return; - - /* free up temp memory */ - lp_talloc_free(); - } -} - -/**************************************************************************** ** - Open the socket communication. - **************************************************************************** */ - -static BOOL open_sockets(BOOL isdaemon, int port) -{ - /* - * The sockets opened here will be used to receive broadcast - * packets *only*. Interface specific sockets are opened in - * make_subnet() in namedbsubnet.c. Thus we bind to the - * address "0.0.0.0". The parameter 'socket address' is - * now deprecated. - */ - - if ( isdaemon ) - ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True); - else - ClientNMB = 0; - - ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True); - - if ( ClientNMB == -1 ) - return( False ); - - /* we are never interested in SIGPIPE */ - BlockSignals(True,SIGPIPE); - - set_socket_options( ClientNMB, "SO_BROADCAST" ); - set_socket_options( ClientDGRAM, "SO_BROADCAST" ); - - DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) ); - return( True ); -} - -/**************************************************************************** ** - main program - **************************************************************************** */ - int main(int argc, const char *argv[]) -{ - static BOOL opt_interactive = False; - poptContext pc; - struct poptOption long_options[] = { - POPT_AUTOHELP - {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" }, - {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" }, - {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, - {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, - {"hosts", 'H', POPT_ARG_STRING, dyn_LMHOSTSFILE, 'H', "Load a netbios hosts file"}, - {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_socket_options }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netbios_name }, - {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_log_base }, - { NULL } - }; - int opt; - pstring logfile; - - global_nmb_port = NMB_PORT; - global_in_nmbd = True; - - StartupTime = time(NULL); - - sys_srandom(time(NULL) ^ sys_getpid()); - - slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - fault_setup((void (*)(void *))fault_continue ); - - /* POSIX demands that signals are inherited. If the invoking process has - * these signals masked, we will have problems, as we won't recieve them. */ - BlockSignals(False, SIGHUP); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGTERM); - - CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); - CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); - -#if defined(SIGFPE) - /* we are never interested in SIGFPE */ - BlockSignals(True,SIGFPE); -#endif - - /* We no longer use USR2... */ -#if defined(SIGUSR2) - BlockSignals(True, SIGUSR2); -#endif - pc = poptGetContext("nmbd", argc, argv, long_options, 0); - - while((opt = poptGetNextOpt(pc)) != -1) - { } - - poptFreeContext(pc); - - if ( opt_interactive ) { - Fork = False; - log_stdout = True; - } - - if ( log_stdout && Fork ) { - DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); - exit(1); - } - - setup_logging( argv[0], log_stdout?DEBUG_STDOUT : DEBUG_FILE ); - - reopen_logs(); - - DEBUG( 0, ( "Netbios nameserver version %s started.\n", VERSION ) ); - DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2002\n" ) ); - - if ( !reload_nmbd_services(False) ) - return(-1); - - if(!init_names()) - return -1; - - reload_nmbd_services( True ); - - if (strequal(lp_workgroup(),"*")) - { - DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); - exit(1); - } - - set_samba_nb_type(); - - if (!is_daemon && !is_a_socket(0)) - { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } - - if (is_daemon && !opt_interactive) - { - DEBUG( 2, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork); - } - -#if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (opt_interactive) - setpgid( (pid_t)0, (pid_t)0 ); -#endif - -#ifndef SYNC_DNS - /* Setup the async dns. We do it here so it doesn't have all the other - stuff initialised and thus chewing memory and sockets */ - if(lp_we_are_a_wins_server() && lp_dns_proxy()) { - start_async_dns(); - } -#endif - - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } - - pidfile_create("nmbd"); - message_init(); - message_register(MSG_FORCE_ELECTION, nmbd_message_election); - message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); - message_register(MSG_SHUTDOWN, nmbd_terminate); - message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info); - - DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); - - if ( !open_sockets( is_daemon, global_nmb_port ) ) { - kill_async_dns_child(); - return 1; - } - - /* Determine all the IP addresses we have. */ - load_interfaces(); - - /* Create an nmbd subnet record for each of the above. */ - if( False == create_subnets() ) - { - DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); - kill_async_dns_child(); - exit(1); - } - - /* Load in any static local names. */ - load_lmhosts_file(dyn_LMHOSTSFILE); - DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE)); - - /* If we are acting as a WINS server, initialise data structures. */ - if( !initialise_wins() ) - { - DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); - kill_async_dns_child(); - exit(1); - } - - /* - * Register nmbd primary workgroup and nmbd names on all - * the broadcast subnets, and on the WINS server (if specified). - * Also initiate the startup of our primary workgroup (start - * elections if we are setup as being able to be a local - * master browser. - */ - - if( False == register_my_workgroup_and_names() ) - { - DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n")); - kill_async_dns_child(); - exit(1); - } - - /* We can only take signals in the select. */ - BlockSignals( True, SIGTERM ); - - process(); - - if (dbf) - x_fclose(dbf); - kill_async_dns_child(); - return(0); -} diff --git a/source4/nmbd/nmbd_become_dmb.c b/source4/nmbd/nmbd_become_dmb.c deleted file mode 100644 index d8122777fe..0000000000 --- a/source4/nmbd/nmbd_become_dmb.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern struct in_addr allones_ip; - -extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ - -static void become_domain_master_browser_bcast(const char *); - -/**************************************************************************** - Fail to become a Domain Master Browser on a subnet. - ****************************************************************************/ - -static void become_domain_master_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *fail_name) -{ - struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_domain_master_fail: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - /* Set the state back to DOMAIN_NONE. */ - work->dom_state = DOMAIN_NONE; - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), work->work_group, subrec->subnet_name)); - return; - } - - /* Update our server status. */ - servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \ -workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); -} - -/**************************************************************************** - Become a Domain Master Browser on a subnet. - ****************************************************************************/ - -static void become_domain_master_stage2(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *registered_name, - uint16 nb_flags, - int ttl, struct in_addr registered_ip) -{ - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_domain_master_stage2: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), registered_name->name, subrec->subnet_name)); - work->dom_state = DOMAIN_NONE; - return; - } - - /* Set the state in the workgroup structure. */ - work->dom_state = DOMAIN_MST; /* Become domain master. */ - - /* Update our server status. */ - servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER); - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\nSamba server %s ", lp_netbios_name() ); - dbgtext( "is now a domain master browser for " ); - dbgtext( "workgroup %s ", work->work_group ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } - - if( subrec == unicast_subnet ) - { - struct nmb_name nmbname; - struct in_addr my_first_ip; - - /* Put our name and first IP address into the - workgroup struct as domain master browser. This - will stop us syncing with ourself if we are also - a local master browser. */ - - make_nmb_name(&nmbname, lp_netbios_name(), 0x20); - - work->dmb_name = nmbname; - /* Pick the first interface ip address as the domain master browser ip. */ - my_first_ip = *iface_n_ip(0); - - putip((char *)&work->dmb_addr, &my_first_ip); - - /* We successfully registered by unicast with the - WINS server. We now expect to become the domain - master on the local subnets. If this fails, it's - probably a 1.9.16p2 to 1.9.16p11 server's fault. - - This is a configuration issue that should be addressed - by the network administrator - you shouldn't have - several machines configured as a domain master browser - for the same WINS scope (except if they are 1.9.17 or - greater, and you know what you're doing. - - see docs/DOMAIN.txt. - - */ - become_domain_master_browser_bcast(work->work_group); - } - else - { - /* - * Now we are a domain master on a broadcast subnet, we need to add - * the WORKGROUP<1b> name to the unicast subnet so that we can answer - * unicast requests sent to this name. This bug wasn't found for a while - * as it is strange to have a DMB without using WINS. JRA. - */ - insert_permanent_name_into_unicast(subrec, registered_name, nb_flags); - } -} - -/**************************************************************************** - Start the name registration process when becoming a Domain Master Browser - on a subnet. - ****************************************************************************/ - -static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name) -{ - struct work_record *work; - - DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \ -workgroup %s on subnet %s\n", wg_name, subrec->subnet_name)); - - /* First, find the workgroup on the subnet. */ - if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) - { - DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n", - wg_name, subrec->subnet_name)); - return; - } - - DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n")); - work->dom_state = DOMAIN_WAIT; - - /* WORKGROUP<1b> is the domain master browser name. */ - register_name(subrec, work->work_group,0x1b,samba_nb_type, - become_domain_master_stage2, - become_domain_master_fail, NULL); -} - -/**************************************************************************** - Function called when a query for a WORKGROUP<1b> name succeeds. - This is normally a fail condition as it means there is already - a domain master browser for a workgroup and we were trying to - become one. -****************************************************************************/ - -static void become_domain_master_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *nmbname, struct in_addr ip, - struct res_rec *rrec) -{ - /* If the given ip is not ours, then we can't become a domain - controler as the name is already registered. - */ - - /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast - address or zero ip for this query. Pretend this is ok. */ - - if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) - { - if( DEBUGLVL( 3 ) ) - { - dbgtext( "become_domain_master_query_success():\n" ); - dbgtext( "Our address (%s) ", inet_ntoa(ip) ); - dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) ); - dbgtext( "(domain master browser name) " ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - dbgtext( "Continuing with domain master code.\n" ); - } - - become_domain_master_stage1(subrec, nmbname->name); - } - else - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_query_success:\n" ); - dbgtext( "There is already a domain master browser at " ); - dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name ); - dbgtext( "registered on subnet %s.\n", subrec->subnet_name ); - } - } -} - -/**************************************************************************** - Function called when a query for a WORKGROUP<1b> name fails. - This is normally a success condition as it then allows us to register - our own Domain Master Browser name. - ****************************************************************************/ - -static void become_domain_master_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, int fail_code) -{ - /* If the query was unicast, and the error is not NAM_ERR (name didn't exist), - then this is a failure. Otherwise, not finding the name is what we want. */ - if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) - { - DEBUG(0,("become_domain_master_query_fail: Error %d returned when \ -querying WINS server for name %s.\n", - fail_code, nmb_namestr(question_name))); - return; - } - - /* Otherwise - not having the name allows us to register it. */ - become_domain_master_stage1(subrec, question_name->name); -} - -/**************************************************************************** - Attempt to become a domain master browser on all broadcast subnets. - ****************************************************************************/ - -static void become_domain_master_browser_bcast(const char *workgroup_name) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name); - - if (work && (work->dom_state == DOMAIN_NONE)) - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,workgroup_name,0x1b); - - /* - * Check for our name on the given broadcast subnet first, only initiate - * further processing if we cannot find it. - */ - - if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_browser_bcast:\n" ); - dbgtext( "Attempting to become domain master browser on " ); - dbgtext( "workgroup %s on subnet %s\n", - workgroup_name, subrec->subnet_name ); - } - - /* Send out a query to establish whether there's a - domain controller on the local subnet. If not, - we can become a domain controller. - */ - - DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \ -for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name)); - - query_name(subrec, nmbname.name, nmbname.name_type, - become_domain_master_query_success, - become_domain_master_query_fail, - NULL); - } - } - } -} - -/**************************************************************************** - Attempt to become a domain master browser by registering with WINS. - ****************************************************************************/ - -static void become_domain_master_browser_wins(const char *workgroup_name) -{ - struct work_record *work; - - work = find_workgroup_on_subnet(unicast_subnet, workgroup_name); - - if (work && (work->dom_state == DOMAIN_NONE)) - { - struct nmb_name nmbname; - - make_nmb_name(&nmbname,workgroup_name,0x1b); - - /* - * Check for our name on the unicast subnet first, only initiate - * further processing if we cannot find it. - */ - - if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_browser_wins:\n" ); - dbgtext( "Attempting to become domain master browser " ); - dbgtext( "on workgroup %s, subnet %s.\n", - workgroup_name, unicast_subnet->subnet_name ); - } - - /* Send out a query to establish whether there's a - domain master broswer registered with WINS. If not, - we can become a domain master browser. - */ - - DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \ -for domain master browser name %s on workgroup %s\n", - inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name)); - - query_name(unicast_subnet, nmbname.name, nmbname.name_type, - become_domain_master_query_success, - become_domain_master_query_fail, - NULL); - } - } -} - -/**************************************************************************** - Add the domain logon server and domain master browser names - if we are set up to do so. - **************************************************************************/ - -void add_domain_names(time_t t) -{ - static time_t lastrun = 0; - - if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60))) - return; - - lastrun = t; - - /* Do the "internet group" - <1c> names. */ - if (lp_domain_logons()) - add_logon_names(); - - /* Do the domain master names. */ - if(lp_server_role() == ROLE_DOMAIN_PDC) - { - if(we_are_a_wins_client()) - { - /* We register the WORKGROUP<1b> name with the WINS - server first, and call add_domain_master_bcast() - only if this is successful. - - This results in domain logon services being gracefully provided, - as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11. - 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c, - cannot provide domain master / domain logon services. - */ - become_domain_master_browser_wins(lp_workgroup()); - } - else - become_domain_master_browser_bcast(lp_workgroup()); - } -} diff --git a/source4/nmbd/nmbd_become_lmb.c b/source4/nmbd/nmbd_become_lmb.c deleted file mode 100644 index 8b87ca7444..0000000000 --- a/source4/nmbd/nmbd_become_lmb.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ - -/******************************************************************* - Utility function to add a name to the unicast subnet, or add in - our IP address if it already exists. -******************************************************************/ - -void insert_permanent_name_into_unicast( struct subnet_record *subrec, - struct nmb_name *nmbname, uint16 nb_type ) -{ - struct name_record *namerec; - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) - { - /* The name needs to be created on the unicast subnet. */ - (void)add_name_to_subnet( unicast_subnet, nmbname->name, - nmbname->name_type, nb_type, - PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip); - } - else - { - /* The name already exists on the unicast subnet. Add our local - IP for the given broadcast subnet to the name. */ - add_ip_to_name_record( namerec, subrec->myip); - } -} - -/******************************************************************* - Utility function to remove a name from the unicast subnet. -******************************************************************/ - -static void remove_permanent_name_from_unicast( struct subnet_record *subrec, - struct nmb_name *nmbname ) -{ - struct name_record *namerec; - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) - { - /* Remove this broadcast subnet IP address from the name. */ - remove_ip_from_name_record( namerec, subrec->myip); - if(namerec->data.num_ips == 0) - remove_name_from_namelist( unicast_subnet, namerec); - } -} - -/******************************************************************* - Utility function always called to set our workgroup and server - state back to potential browser, or none. -******************************************************************/ - -static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name, - BOOL force_new_election ) -{ - struct work_record *work; - struct server_record *servrec; - struct nmb_name nmbname; - - if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) - { - DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \ -subnet %s.\n", workgroup_name, subrec->subnet_name )); - return; - } - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), work->work_group, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } - - /* Update our server status - remove any master flag and replace - it with the potential browser flag. */ - servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER; - servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0); - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* Reset our election flags. */ - work->ElectionCriterion &= ~0x4; - - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - - /* Forget who the local master browser was for - this workgroup. */ - - set_workgroup_local_master_browser_name( work, ""); - - /* - * Ensure the IP address of this subnet is not registered as one - * of the IP addresses of the WORKGROUP<1d> name on the unicast - * subnet. This undoes what we did below when we became a local - * master browser. - */ - - make_nmb_name(&nmbname, work->work_group, 0x1d); - - remove_permanent_name_from_unicast( subrec, &nmbname); - - if(force_new_election) - work->needelection = True; -} - -/******************************************************************* - Unbecome the local master browser name release success function. -******************************************************************/ - -static void unbecome_local_master_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *released_name, - struct in_addr released_ip) -{ - BOOL force_new_election = False; - - memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); - - DEBUG(3,("unbecome_local_master_success: released name %s.\n", - nmb_namestr(released_name))); - - /* Now reset the workgroup and server state. */ - reset_workgroup_state( subrec, released_name->name, force_new_election ); - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", lp_netbios_name() ); - dbgtext( "has stopped being a local master browser " ); - dbgtext( "for workgroup %s ", released_name->name ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } - -} - -/******************************************************************* - Unbecome the local master browser name release fail function. -******************************************************************/ - -static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec, - struct nmb_name *fail_name) -{ - struct name_record *namerec; - struct userdata_struct *userdata = rrec->userdata; - BOOL force_new_election = False; - - memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); - - DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \ -Removing from namelist anyway.\n", nmb_namestr(fail_name))); - - /* Do it anyway. */ - namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); - if(namerec) - remove_name_from_namelist(subrec, namerec); - - /* Now reset the workgroup and server state. */ - reset_workgroup_state( subrec, fail_name->name, force_new_election ); - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", lp_netbios_name() ); - dbgtext( "has stopped being a local master browser " ); - dbgtext( "for workgroup %s ", fail_name->name ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } -} - -/******************************************************************* - Utility function to remove the WORKGROUP<1d> name. -******************************************************************/ - -static void release_1d_name( struct subnet_record *subrec, char *workgroup_name, - BOOL force_new_election) -{ - struct nmb_name nmbname; - struct name_record *namerec; - - make_nmb_name(&nmbname, workgroup_name, 0x1d); - if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) - { - struct userdata_struct *userdata; - int size = sizeof(struct userdata_struct) + sizeof(BOOL); - - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0,("release_1d_name: malloc fail.\n")); - return; - } - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(BOOL); - memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL)); - - release_name(subrec, namerec, - unbecome_local_master_success, - unbecome_local_master_fail, - userdata); - - zero_free(userdata, size); - } -} - -/******************************************************************* - Unbecome the local master browser MSBROWSE name release success function. -******************************************************************/ - -static void release_msbrowse_name_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *released_name, - struct in_addr released_ip) -{ - DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.", - nmb_namestr(released_name), subrec->subnet_name )); - - /* Remove the permanent MSBROWSE name added into the unicast subnet. */ - remove_permanent_name_from_unicast( subrec, released_name); -} - -/******************************************************************* - Unbecome the local master browser MSBROWSE name release fail function. -******************************************************************/ - -static void release_msbrowse_name_fail( struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *fail_name) -{ - struct name_record *namerec; - - DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.", - nmb_namestr(fail_name), subrec->subnet_name )); - - /* Release the name anyway. */ - namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); - if(namerec) - remove_name_from_namelist(subrec, namerec); - - /* Remove the permanent MSBROWSE name added into the unicast subnet. */ - remove_permanent_name_from_unicast( subrec, fail_name); -} - -/******************************************************************* - Unbecome the local master browser. If force_new_election is true, restart - the election process after we've unbecome the local master. -******************************************************************/ - -void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work, - BOOL force_new_election) -{ - struct name_record *namerec; - struct nmb_name nmbname; - - /* Sanity check. */ - - DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \ -on subnet %s\n",work->work_group, subrec->subnet_name)); - - if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) - { - DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), work->work_group, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } - - /* Set the state to unbecoming. */ - work->mst_state = MST_UNBECOMING_MASTER; - - /* - * Release the WORKGROUP<1d> name asap to allow another machine to - * claim it. - */ - - release_1d_name( subrec, work->work_group, force_new_election); - - /* Deregister any browser names we may have. */ - make_nmb_name(&nmbname, MSBROWSE, 0x1); - if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) - { - release_name(subrec, namerec, - release_msbrowse_name_success, - release_msbrowse_name_fail, - NULL); - } - - /* - * Ensure we have sent and processed these release packets - * before returning - we don't want to process any election - * packets before dealing with the 1d release. - */ - - retransmit_or_expire_response_records(time(NULL)); -} - -/**************************************************************************** - Success in registering the WORKGROUP<1d> name. - We are now *really* a local master browser. - ****************************************************************************/ - -static void become_local_master_stage2(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *registered_name, - uint16 nb_flags, - int ttl, struct in_addr registered_ip) -{ - int i = 0; - struct server_record *sl; - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_local_master_stage2: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), registered_name->name, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } - - DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \ -on subnet %s\n", work->work_group, subrec->subnet_name)); - - work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */ - - /* update our server status */ - servrec->serv.type |= SV_TYPE_MASTER_BROWSER; - servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* Add this name to the workgroup as local master browser. */ - set_workgroup_local_master_browser_name( work, lp_netbios_name()); - - /* Count the number of servers we have on our list. If it's - less than 10 (just a heuristic) request the servers - to announce themselves. - */ - for( sl = work->serverlist; sl != NULL; sl = sl->next) - i++; - - if (i < 10) - { - /* Ask all servers on our local net to announce to us. */ - broadcast_announce_request(subrec, work); - } - - /* - * Now we are a local master on a broadcast subnet, we need to add - * the WORKGROUP<1d> name to the unicast subnet so that we can answer - * unicast requests sent to this name. We can create this name directly on - * the unicast subnet as a WINS server always returns true when registering - * this name, and discards the registration. We use the number of IP - * addresses registered to this name as a reference count, as we - * remove this broadcast subnet IP address from it when we stop becoming a local - * master browser for this broadcast subnet. - */ - - insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); - - /* Reset the announce master browser timer so that we try and tell a domain - master browser as soon as possible that we are a local master browser. */ - reset_announce_timer(); - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", lp_netbios_name() ); - dbgtext( "is now a local master browser " ); - dbgtext( "for workgroup %s ", work->work_group ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } - -} - -/**************************************************************************** - Failed to register the WORKGROUP<1d> name. - ****************************************************************************/ -static void become_local_master_fail2(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *fail_name) -{ - struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name); - - DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \ -Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name)); - - if(!work) - { - DEBUG(0,("become_local_master_fail2: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - /* Roll back all the way by calling unbecome_local_master_browser(). */ - unbecome_local_master_browser(subrec, work, False); -} - -/**************************************************************************** - Success in registering the MSBROWSE name. - ****************************************************************************/ - -static void become_local_master_stage1(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *registered_name, - uint16 nb_flags, - int ttl, struct in_addr registered_ip) -{ - char *work_name = userdata->data; - struct work_record *work = find_workgroup_on_subnet( subrec, work_name); - - if(!work) - { - DEBUG(0,("become_local_master_stage1: Error - cannot find \ -workgroup %s on subnet %s\n", work_name, subrec->subnet_name)); - return; - } - - DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n", - work->work_group)); - - work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */ - - /* - * We registered the MSBROWSE name on a broadcast subnet, now need to add - * the MSBROWSE name to the unicast subnet so that we can answer - * unicast requests sent to this name. We create this name directly on - * the unicast subnet. - */ - - insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); - - /* Attempt to register the WORKGROUP<1d> name. */ - register_name(subrec, work->work_group,0x1d,samba_nb_type, - become_local_master_stage2, - become_local_master_fail2, - NULL); -} - -/**************************************************************************** - Failed to register the MSBROWSE name. - ****************************************************************************/ - -static void become_local_master_fail1(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *fail_name) -{ - char *work_name = rrec->userdata->data; - struct work_record *work = find_workgroup_on_subnet(subrec, work_name); - - if(!work) - { - DEBUG(0,("become_local_master_fail1: Error - cannot find \ -workgroup %s on subnet %s\n", work_name, subrec->subnet_name)); - return; - } - - if(find_server_in_workgroup(work, lp_netbios_name()) == NULL) - { - DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), work->work_group, subrec->subnet_name)); - return; - } - - reset_workgroup_state( subrec, work->work_group, False ); - - DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \ -workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); -} - -/****************************************************************** - Become the local master browser on a subnet. - This gets called if we win an election on this subnet. - - Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1. - Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>. - Stage 3: mst_state was MST_MSB - go to MST_BROWSER. -******************************************************************/ - -void become_local_master_browser(struct subnet_record *subrec, struct work_record *work) -{ - struct userdata_struct *userdata; - int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1; - - /* Sanity check. */ - if (!lp_local_master()) - { - DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n")); - return; - } - - if(!AM_POTENTIAL_MASTER_BROWSER(work)) - { - DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n", - work->mst_state )); - return; - } - - if(find_server_in_workgroup( work, lp_netbios_name()) == NULL) - { - DEBUG(0,("become_local_master_browser: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), work->work_group, subrec->subnet_name)); - return; - } - - DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \ -%s on subnet %s\n", work->work_group, subrec->subnet_name)); - - DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n")); - work->mst_state = MST_BACKUP; /* an election win was successful */ - - work->ElectionCriterion |= 0x5; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* Setup the userdata_struct. */ - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0,("become_local_master_browser: malloc fail.\n")); - return; - } - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = strlen(work->work_group)+1; - fstrcpy(userdata->data, work->work_group); - - /* Register the special browser group name. */ - register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP, - become_local_master_stage1, - become_local_master_fail1, - userdata); - - zero_free(userdata, size); -} - -/*************************************************************** - Utility function to set the local master browser name. Does - some sanity checking as old versions of Samba seem to sometimes - say that the master browser name for a workgroup is the same - as the workgroup name. -****************************************************************/ - -void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname) -{ - DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \ -for workgroup %s.\n", newname, work->work_group )); - -#if 0 - /* - * Apparently some sites use the workgroup name as the local - * master browser name. Arrrrggghhhhh ! (JRA). - */ - if(strequal( work->work_group, newname)) - { - DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \ -local_master_browser_name for workgroup %s to workgroup name.\n", - work->work_group )); - return; - } -#endif - - StrnCpy(work->local_master_browser_name, newname, - sizeof(work->local_master_browser_name)-1); -} diff --git a/source4/nmbd/nmbd_browserdb.c b/source4/nmbd/nmbd_browserdb.c deleted file mode 100644 index a4ef98e265..0000000000 --- a/source4/nmbd/nmbd_browserdb.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - Copyright (C) Christopher R. Hertel 1998 - - 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. - -*/ -/* -------------------------------------------------------------------------- ** - * Modified July 1998 by CRH. - * I converted this module to use the canned doubly-linked lists. I also - * added comments above the functions where possible. - */ - -#include "includes.h" - -/* -------------------------------------------------------------------------- ** - * Variables... - * - * lmb_browserlist - This is our local master browser list. - */ - -ubi_dlNewList( lmb_browserlist ); - - -/* -------------------------------------------------------------------------- ** - * Functions... - */ - -/* ************************************************************************** ** - * Remove and free a browser list entry. - * - * Input: browc - A pointer to the entry to be removed from the list and - * freed. - * Output: none. - * - * ************************************************************************** ** - */ -static void remove_lmb_browser_entry( struct browse_cache_record *browc ) - { - safe_free( ubi_dlRemThis( lmb_browserlist, browc ) ); - } /* remove_lmb_browser_entry */ - -/* ************************************************************************** ** - * Update a browser death time. - * - * Input: browc - Pointer to the entry to be updated. - * Output: none. - * - * ************************************************************************** ** - */ -void update_browser_death_time( struct browse_cache_record *browc ) - { - /* Allow the new lmb to miss an announce period before we remove it. */ - browc->death_time = time(NULL) + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); - } /* update_browser_death_time */ - -/* ************************************************************************** ** - * Create a browser entry and add it to the local master browser list. - * - * Input: work_name - * browser_name - * ip - * - * Output: Pointer to the new entry, or NULL if malloc() failed. - * - * ************************************************************************** ** - */ -struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, - char *browser_name, - struct in_addr ip ) - { - struct browse_cache_record *browc; - time_t now = time( NULL ); - - browc = (struct browse_cache_record *)malloc( sizeof( *browc ) ); - - if( NULL == browc ) - { - DEBUG( 0, ("create_browser_in_lmb_cache: malloc fail !\n") ); - return( NULL ); - } - - memset( (char *)browc, '\0', sizeof( *browc ) ); - - /* For a new lmb entry we want to sync with it after one minute. This - will allow it time to send out a local announce and build its - browse list. - */ - browc->sync_time = now + 60; - - /* Allow the new lmb to miss an announce period before we remove it. */ - browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); - - StrnCpy( browc->lmb_name, browser_name, sizeof(browc->lmb_name)-1 ); - StrnCpy( browc->work_group, work_name, sizeof(browc->work_group)-1 ); - strupper( browc->lmb_name ); - strupper( browc->work_group ); - - browc->ip = ip; - - (void)ubi_dlAddTail( lmb_browserlist, browc ); - - if( DEBUGLVL( 3 ) ) - { - Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" ); - Debug1( " Added lmb cache entry for workgroup %s ", browc->work_group ); - Debug1( "name %s IP %s ", browc->lmb_name, inet_ntoa(ip) ); - Debug1( "ttl %d\n", (int)browc->death_time ); - } - - return( browc ); - } /* create_browser_in_lmb_cache */ - -/* ************************************************************************** ** - * Find a browser entry in the local master browser list. - * - * Input: browser_name - The name for which to search. - * - * Output: A pointer to the matching entry, or NULL if no match was found. - * - * ************************************************************************** ** - */ -struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name ) - { - struct browse_cache_record *browc; - - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) - if( strequal( browser_name, browc->lmb_name ) ) - break; - - return( browc ); - } /* find_browser_in_lmb_cache */ - -/* ************************************************************************** ** - * Expire timed out browsers in the browserlist. - * - * Input: t - Expiration time. Entries with death times less than this - * value will be removed from the list. - * Output: none. - * - * ************************************************************************** ** - */ -void expire_lmb_browsers( time_t t ) - { - struct browse_cache_record *browc; - struct browse_cache_record *nextbrowc; - - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = nextbrowc ) - { - nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc ); - - if( browc->death_time < t ) - { - if( DEBUGLVL( 3 ) ) - { - Debug1( "nmbd_browserdb:expire_lmb_browsers()\n" ); - Debug1( " Removing timed out lmb entry %s\n", browc->lmb_name ); - } - remove_lmb_browser_entry( browc ); - } - } - } /* expire_lmb_browsers */ diff --git a/source4/nmbd/nmbd_browsesync.c b/source4/nmbd/nmbd_browsesync.c deleted file mode 100644 index ff022a7bb1..0000000000 --- a/source4/nmbd/nmbd_browsesync.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/* This is our local master browser list database. */ -extern ubi_dlList lmb_browserlist[]; - -/**************************************************************************** -As a domain master browser, do a sync with a local master browser. -**************************************************************************/ -static void sync_with_lmb(struct browse_cache_record *browc) -{ - struct work_record *work; - - if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "Failed to get a workgroup for a local master browser " ); - dbgtext( "cache entry workgroup " ); - dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name ); - } - return; - } - - /* We should only be doing this if we are a domain master browser for - the given workgroup. Ensure this is so. */ - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "We are trying to sync with a local master browser " ); - dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group ); - dbgtext( "and we are not a domain master browser on this workgroup.\n" ); - dbgtext( "Error!\n" ); - } - return; - } - - if( DEBUGLVL( 2 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "Initiating sync with local master browser " ); - dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) ); - dbgtext( "for workgroup %s\n", browc->work_group ); - } - - sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True); - - browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60); -} - -/**************************************************************************** -Sync or expire any local master browsers. -**************************************************************************/ -void dmb_expire_and_sync_browser_lists(time_t t) -{ - static time_t last_run = 0; - struct browse_cache_record *browc; - - /* Only do this every 20 seconds. */ - if (t - last_run < 20) - return; - - last_run = t; - - expire_lmb_browsers(t); - - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) - { - if (browc->sync_time < t) - sync_with_lmb(browc); - } -} - -/**************************************************************************** -As a local master browser, send an announce packet to the domain master browser. -**************************************************************************/ - -static void announce_local_master_browser_to_domain_master_browser( struct work_record *work) -{ - pstring outbuf; - char *p; - - if(ismyip(work->dmb_addr)) - { - if( DEBUGLVL( 2 ) ) - { - dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); - dbgtext( "We are both a domain and a local master browser for " ); - dbgtext( "workgroup %s. ", work->work_group ); - dbgtext( "Do not announce to ourselves.\n" ); - } - return; - } - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_MasterAnnouncement); - p++; - - StrnCpy(p,lp_netbios_name(),15); - strupper(p); - p = skip_string(p,1); - - if( DEBUGLVL( 4 ) ) - { - dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); - dbgtext( "Sending local master announce to " ); - dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name), - work->work_group ); - } - - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - lp_netbios_name(), 0x0, work->dmb_name.name, 0x0, - work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT); - -} - -/**************************************************************************** -As a local master browser, do a sync with a domain master browser. -**************************************************************************/ - -static void sync_with_dmb(struct work_record *work) -{ - if( DEBUGLVL( 2 ) ) - { - dbgtext( "sync_with_dmb:\n" ); - dbgtext( "Initiating sync with domain master browser " ); - dbgtext( "%s ", nmb_namestr(&work->dmb_name) ); - dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) ); - dbgtext( "for workgroup %s\n", work->work_group ); - } - - sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type, - work->dmb_addr, False, True); -} - -/**************************************************************************** - Function called when a node status query to a domain master browser IP succeeds. -****************************************************************************/ - -static void domain_master_node_status_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct res_rec *answers, - struct in_addr from_ip) -{ - struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data); - - if( work == NULL ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Unable to find workgroup " ); - dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name ); - } - return; - } - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Success in node status for workgroup " ); - dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) ); - } - - /* Go through the list of names found at answers->rdata and look for - the first SERVER<0x20> name. */ - - if(answers->rdata != NULL) - { - char *p = answers->rdata; - int numnames = CVAL(p, 0); - - p += 1; - - while (numnames--) - { - char qname[17]; - uint16 nb_flags; - int name_type; - - StrnCpy(qname,p,15); - name_type = CVAL(p,15); - nb_flags = get_nb_flags(&p[16]); - trim_string(qname,NULL," "); - - p += 18; - - if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) - { - struct nmb_name nmbname; - - make_nmb_name(&nmbname, qname, name_type); - - /* Copy the dmb name and IP address - into the workgroup struct. */ - - work->dmb_name = nmbname; - putip((char *)&work->dmb_addr, &from_ip); - - /* Do the local master browser announcement to the domain - master browser name and IP. */ - announce_local_master_browser_to_domain_master_browser( work ); - - /* Now synchronise lists with the domain master browser. */ - sync_with_dmb(work); - break; - } - } - } - else - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " ); - dbgtext( "%s.\n", inet_ntoa(from_ip) ); - } -} - -/**************************************************************************** - Function called when a node status query to a domain master browser IP fails. -****************************************************************************/ - -static void domain_master_node_status_fail(struct subnet_record *subrec, - struct response_record *rrec) -{ - struct userdata_struct *userdata = rrec->userdata; - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_fail:\n" ); - dbgtext( "Doing a node status request to the domain master browser\n" ); - dbgtext( "for workgroup %s ", userdata->data ); - dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); - dbgtext( "Cannot sync browser lists.\n" ); - } -} - -/**************************************************************************** - Function called when a query for a WORKGROUP<1b> name succeeds. -****************************************************************************/ - -static void find_domain_master_name_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata_in, - struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) -{ - /* - * Unfortunately, finding the IP address of the Domain Master Browser, - * as we have here, is not enough. We need to now do a sync to the - * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will - * respond to the SMBSERVER name. To get this name from IP - * address we do a Node status request, and look for the first - * NAME<0x20> in the response, and take that as the server name. - * We also keep a cache of the Domain Master Browser name for this - * workgroup in the Workgroup struct, so that if the same IP addess - * is returned every time, we don't need to do the node status - * request. - */ - - struct work_record *work; - struct nmb_name nmbname; - struct userdata_struct *userdata; - int size = sizeof(struct userdata_struct) + sizeof(fstring)+1; - - if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "find_domain_master_name_query_success:\n" ); - dbgtext( "Failed to find workgroup %s\n", q_name->name ); - } - return; - } - - /* First check if we already have a dmb for this workgroup. */ - - if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) - { - /* Do the local master browser announcement to the domain - master browser name and IP. */ - announce_local_master_browser_to_domain_master_browser( work ); - - /* Now synchronise lists with the domain master browser. */ - sync_with_dmb(work); - return; - } - else - zero_ip(&work->dmb_addr); - - /* Now initiate the node status request. */ - make_nmb_name(&nmbname,"*",0x0); - - /* Put the workgroup name into the userdata so we know - what workgroup we're talking to when the reply comes - back. */ - - /* Setup the userdata_struct - this is copied so we can use - a stack variable for this. */ - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n")); - return; - } - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = strlen(work->work_group)+1; - fstrcpy(userdata->data, work->work_group); - - node_status( subrec, &nmbname, answer_ip, - domain_master_node_status_success, - domain_master_node_status_fail, - userdata); - - zero_free(userdata, size); -} - -/**************************************************************************** - Function called when a query for a WORKGROUP<1b> name fails. - ****************************************************************************/ -static void find_domain_master_name_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, int fail_code) -{ - if( DEBUGLVL( 0 ) ) - { - dbgtext( "find_domain_master_name_query_fail:\n" ); - dbgtext( "Unable to find the Domain Master Browser name " ); - dbgtext( "%s for the workgroup %s.\n", - nmb_namestr(question_name), question_name->name ); - dbgtext( "Unable to sync browse lists in this workgroup.\n" ); - } -} - -/**************************************************************************** -As a local master browser for a workgroup find the domain master browser -name, announce ourselves as local master browser to it and then pull the -full domain browse lists from it onto the given subnet. -**************************************************************************/ - -void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec, - struct work_record *work) -{ - struct nmb_name nmbname; - - /* Only do this if we are using a WINS server. */ - if(we_are_a_wins_client() == False) - { - if( DEBUGLVL( 10 ) ) - { - dbgtext( "announce_and_sync_with_domain_master_browser:\n" ); - dbgtext( "Ignoring, as we are not a WINS client.\n" ); - } - return; - } - - make_nmb_name(&nmbname,work->work_group,0x1b); - - /* First, query for the WORKGROUP<1b> name from the WINS server. */ - query_name(unicast_subnet, nmbname.name, nmbname.name_type, - find_domain_master_name_query_success, - find_domain_master_name_query_fail, - NULL); - -} - -/**************************************************************************** - Function called when a node status query to a domain master browser IP succeeds. - This function is only called on query to a Samba 1.9.18 or above WINS server. - - Note that adding the workgroup name is enough for this workgroup to be - browsable by clients, as clients query the WINS server or broadcast - nets for the WORKGROUP<1b> name when they want to browse a workgroup - they are not in. We do not need to do a sync with this Domain Master - Browser in order for our browse clients to see machines in this workgroup. - JRA. -****************************************************************************/ - -static void get_domain_master_name_node_status_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct res_rec *answers, - struct in_addr from_ip) -{ - struct work_record *work; - fstring server_name; - - server_name[0] = 0; - - if( DEBUGLVL( 3 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) ); - } - - /* - * Go through the list of names found at answers->rdata and look for - * the first WORKGROUP<0x1b> name. - */ - - if(answers->rdata != NULL) - { - char *p = answers->rdata; - int numnames = CVAL(p, 0); - - p += 1; - - while (numnames--) - { - char qname[17]; - uint16 nb_flags; - int name_type; - - StrnCpy(qname,p,15); - name_type = CVAL(p,15); - nb_flags = get_nb_flags(&p[16]); - trim_string(qname,NULL," "); - - p += 18; - - if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && - server_name[0] == 0) { - /* this is almost certainly the server netbios name */ - fstrcpy(server_name, qname); - continue; - } - - if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) ); - dbgtext( "is a domain master browser for workgroup " ); - dbgtext( "%s. Adding this name.\n", qname ); - } - - /* - * If we don't already know about this workgroup, add it - * to the workgroup list on the unicast_subnet. - */ - if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) - { - struct nmb_name nmbname; - /* - * Add it - with an hour in the cache. - */ - if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60))) - return; - - /* remember who the master is */ - fstrcpy(work->local_master_browser_name, server_name); - make_nmb_name(&nmbname, server_name, 0x20); - work->dmb_name = nmbname; - work->dmb_addr = from_ip; - } - break; - } - } - } - else - if( DEBUGLVL( 0 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " ); - dbgtext( "%s.\n", inet_ntoa(from_ip) ); - } -} - -/**************************************************************************** - Function called when a node status query to a domain master browser IP fails. -****************************************************************************/ - -static void get_domain_master_name_node_status_fail(struct subnet_record *subrec, - struct response_record *rrec) -{ - if( DEBUGLVL( 0 ) ) - { - dbgtext( "get_domain_master_name_node_status_fail:\n" ); - dbgtext( "Doing a node status request to the domain master browser " ); - dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); - dbgtext( "Cannot get workgroup name.\n" ); - } -} - -/**************************************************************************** - Function called when a query for *<1b> name succeeds. -****************************************************************************/ - -static void find_all_domain_master_names_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata_in, - struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) -{ - /* - * We now have a list of all the domain master browsers for all workgroups - * that have registered with the WINS server. Now do a node status request - * to each one and look for the first 1b name in the reply. This will be - * the workgroup name that we will add to the unicast subnet as a 'non-local' - * workgroup. - */ - - struct nmb_name nmbname; - struct in_addr send_ip; - int i; - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_succes:\n" ); - dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) ); - dbgtext( "IP addresses for Domain Master Browsers.\n" ); - } - - for(i = 0; i < rrec->rdlength / 6; i++) - { - /* Initiate the node status requests. */ - make_nmb_name(&nmbname, "*", 0); - - putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]); - - /* - * Don't send node status requests to ourself. - */ - - if(ismyip( send_ip )) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_succes:\n" ); - dbgtext( "Not sending node status to our own IP " ); - dbgtext( "%s.\n", inet_ntoa(send_ip) ); - } - continue; - } - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_success:\n" ); - dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) ); - } - - node_status( subrec, &nmbname, send_ip, - get_domain_master_name_node_status_success, - get_domain_master_name_node_status_fail, - NULL); - } -} - -/**************************************************************************** - Function called when a query for *<1b> name fails. - ****************************************************************************/ -static void find_all_domain_master_names_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, int fail_code) -{ - if( DEBUGLVL( 10 ) ) - { - dbgtext( "find_domain_master_name_query_fail:\n" ); - dbgtext( "WINS server did not reply to a query for name " ); - dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) ); - dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" ); - } -} - -/**************************************************************************** - If we are a domain master browser on the unicast subnet, do a query to the - WINS server for the *<1b> name. This will only work to a Samba WINS server, - so ignore it if we fail. If we succeed, contact each of the IP addresses in - turn and do a node status request to them. If this succeeds then look for a - <1b> name in the reply - this is the workgroup name. Add this to the unicast - subnet. This is expensive, so we only do this every 15 minutes. -**************************************************************************/ -void collect_all_workgroup_names_from_wins_server(time_t t) -{ - static time_t lastrun = 0; - struct work_record *work; - struct nmb_name nmbname; - - /* Only do this if we are using a WINS server. */ - if(we_are_a_wins_client() == False) - return; - - /* Check to see if we are a domain master browser on the unicast subnet. */ - if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "collect_all_workgroup_names_from_wins_server:\n" ); - dbgtext( "Cannot find my workgroup %s ", lp_workgroup() ); - dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name ); - } - return; - } - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - return; - - if ((lastrun != 0) && (t < lastrun + (15 * 60))) - return; - - lastrun = t; - - make_nmb_name(&nmbname,"*",0x1b); - - /* First, query for the *<1b> name from the WINS server. */ - query_name(unicast_subnet, nmbname.name, nmbname.name_type, - find_all_domain_master_names_query_success, - find_all_domain_master_names_query_fail, - NULL); -} - - -/**************************************************************************** - If we are a domain master browser on the unicast subnet, do a regular sync - with all other DMBs that we know of on that subnet. - -To prevent exponential network traffic with large numbers of workgroups -we use a randomised system where sync probability is inversely proportional -to the number of known workgroups -**************************************************************************/ -void sync_all_dmbs(time_t t) -{ - static time_t lastrun = 0; - struct work_record *work; - int count=0; - - /* Only do this if we are using a WINS server. */ - if(we_are_a_wins_client() == False) - return; - - /* Check to see if we are a domain master browser on the - unicast subnet. */ - work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup()); - if (!work) return; - - if (!AM_DOMAIN_MASTER_BROWSER(work)) - return; - - if ((lastrun != 0) && (t < lastrun + (5 * 60))) - return; - - /* count how many syncs we might need to do */ - for (work=unicast_subnet->workgrouplist; work; work = work->next) { - if (strcmp(lp_workgroup(), work->work_group)) { - count++; - } - } - - /* sync with a probability of 1/count */ - for (work=unicast_subnet->workgrouplist; work; work = work->next) { - if (strcmp(lp_workgroup(), work->work_group)) { - if (((unsigned)sys_random()) % count != 0) continue; - - lastrun = t; - - if (!work->dmb_name.name[0]) { - /* we don't know the DMB - assume it is - the same as the unicast local master */ - make_nmb_name(&work->dmb_name, - work->local_master_browser_name, - 0x20); - } - - DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n", - work->dmb_name.name, - inet_ntoa(work->dmb_addr))); - sync_browse_lists(work, - work->dmb_name.name, - work->dmb_name.name_type, - work->dmb_addr, False, False); - } - } -} diff --git a/source4/nmbd/nmbd_elections.c b/source4/nmbd/nmbd_elections.c deleted file mode 100644 index 759379cc84..0000000000 --- a/source4/nmbd/nmbd_elections.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/* Election parameters. */ -extern time_t StartupTime; - -/**************************************************************************** - Send an election datagram packet. -**************************************************************************/ -static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name, - uint32 criterion, int timeup,const char *server_name) -{ - pstring outbuf; - char *p; - - DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n", - workgroup_name, subrec->subnet_name )); - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_Election); /* Election opcode. */ - p++; - - SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION)); - SIVAL(p,1,criterion); - SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */ - p += 13; - pstrcpy(p,server_name); - strupper(p); - p = skip_string(p,1); - - send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - lp_netbios_name(), 0, - workgroup_name, 0x1e, - subrec->bcast_ip, subrec->myip, DGRAM_PORT); -} - -/******************************************************************* - We found a current master browser on one of our broadcast interfaces. -******************************************************************/ - -static void check_for_master_browser_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *answer_name, - struct in_addr answer_ip, struct res_rec *rrec) -{ - DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \ -IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) )); -} - -/******************************************************************* - We failed to find a current master browser on one of our broadcast interfaces. -******************************************************************/ - -static void check_for_master_browser_fail( struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, - int fail_code) -{ - char *workgroup_name = question_name->name; - struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name); - - if(work == NULL) - { - DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n", - workgroup_name, subrec->subnet_name )); - return; - } - - if (strequal(work->work_group, lp_workgroup())) - { - - if (lp_local_master()) - { - /* We have discovered that there is no local master - browser, and we are configured to initiate - an election that we will participate in. - */ - DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n", - work->work_group, subrec->subnet_name )); - - /* Setting this means we will participate when the - election is run in run_elections(). */ - work->needelection = True; - } - else - { - /* We need to force an election, because we are configured - not to become the local master, but we still need one, - having detected that one doesn't exist. - */ - send_election_dgram(subrec, work->work_group, 0, 0, ""); - } - } -} - -/******************************************************************* - Ensure there is a local master browser for a workgroup on our - broadcast interfaces. -******************************************************************/ - -void check_master_browser_exists(time_t t) -{ - static time_t lastrun=0; - struct subnet_record *subrec; - const char *workgroup_name = lp_workgroup(); - - if (!lastrun) - lastrun = t; - - if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60))) - return; - - lastrun = t; - - dump_workgroups(False); - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - - for (work = subrec->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) - { - /* Do a name query for the local master browser on this net. */ - query_name( subrec, work->work_group, 0x1d, - check_for_master_browser_success, - check_for_master_browser_fail, - NULL); - } - } - } -} - -/******************************************************************* - Run an election. -******************************************************************/ - -void run_elections(time_t t) -{ - static time_t lastime = 0; - - struct subnet_record *subrec; - - /* Send election packets once every 2 seconds - note */ - if (lastime && (t - lastime < 2)) - return; - - lastime = t; - - START_PROFILE(run_elections); - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - - for (work = subrec->workgrouplist; work; work = work->next) - { - if (work->RunningElection) - { - /* - * We can only run an election for a workgroup if we have - * registered the WORKGROUP<1e> name, as that's the name - * we must listen to. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, work->work_group, 0x1e); - if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { - DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \ -yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); - continue; - } - - send_election_dgram(subrec, work->work_group, work->ElectionCriterion, - t - StartupTime, lp_netbios_name()); - - if (work->ElectionCount++ >= 4) - { - /* Won election (4 packets were sent out uncontested. */ - DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - - work->RunningElection = False; - - become_local_master_browser(subrec, work); - } - } - } - } - END_PROFILE(run_elections); -} - -/******************************************************************* - Determine if I win an election. -******************************************************************/ - -static BOOL win_election(struct work_record *work, int version, - uint32 criterion, int timeup, char *server_name) -{ - int mytimeup = time(NULL) - StartupTime; - uint32 mycriterion = work->ElectionCriterion; - - /* If local master is false then never win - in election broadcasts. */ - if(!lp_local_master()) - { - DEBUG(3,("win_election: Losing election as local master == False\n")); - return False; - } - - DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n", - version, ELECTION_VERSION, - criterion, mycriterion, - timeup, mytimeup, - server_name, lp_netbios_name())); - - if (version > ELECTION_VERSION) - return(False); - if (version < ELECTION_VERSION) - return(True); - - if (criterion > mycriterion) - return(False); - if (criterion < mycriterion) - return(True); - - if (timeup > mytimeup) - return(False); - if (timeup < mytimeup) - return(True); - - if (strcasecmp(lp_netbios_name(), server_name) > 0) - return(False); - - return(True); -} - -/******************************************************************* - Process an incoming election datagram packet. -******************************************************************/ - -void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int version = CVAL(buf,0); - uint32 criterion = IVAL(buf,1); - int timeup = IVAL(buf,5)/1000; - char *server_name = buf+13; - struct work_record *work; - char *workgroup_name = dgram->dest_name.name; - - START_PROFILE(election); - server_name[15] = 0; - - DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n", - server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name )); - - DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup)); - - if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n", - workgroup_name, subrec->subnet_name )); - goto done; - } - - if (!strequal(work->work_group, lp_workgroup())) - { - DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \ -is not my workgroup.\n", work->work_group, subrec->subnet_name )); - goto done; - } - - if (win_election(work, version,criterion,timeup,server_name)) - { - /* We take precedence over the requesting server. */ - if (!work->RunningElection) - { - /* We weren't running an election - start running one. */ - - work->needelection = True; - work->ElectionCount=0; - } - - /* Note that if we were running an election for this workgroup on this - subnet already, we just ignore the server we take precedence over. */ - } - else - { - /* We lost. Stop participating. */ - work->needelection = False; - - if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) - { - work->RunningElection = False; - DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - if (AM_LOCAL_MASTER_BROWSER(work)) - unbecome_local_master_browser(subrec, work, False); - } - } -done: - END_PROFILE(election); -} - -/**************************************************************************** - This function looks over all the workgroups known on all the broadcast - subnets and decides if a browser election is to be run on that workgroup. - It returns True if any election packets need to be sent (this will then - be done by run_elections(). -***************************************************************************/ - -BOOL check_elections(void) -{ - struct subnet_record *subrec; - BOOL run_any_election = False; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - run_any_election |= work->RunningElection; - - /* - * Start an election if we have any chance of winning. - * Note this is a change to the previous code, that would - * only run an election if nmbd was in the potential browser - * state. We need to run elections in any state if we're told - * to. JRA. - */ - - if (work->needelection && !work->RunningElection && lp_local_master()) - { - /* - * We can only run an election for a workgroup if we have - * registered the WORKGROUP<1e> name, as that's the name - * we must listen to. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, work->work_group, 0x1e); - if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { - DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \ -yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); - continue; - } - - DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - - work->ElectionCount = 0; - work->RunningElection = True; - work->needelection = False; - } - } - } - return run_any_election; -} - - - -/**************************************************************************** -process a internal Samba message forcing an election -***************************************************************************/ -void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) { - if (strequal(work->work_group, lp_workgroup())) { - work->needelection = True; - work->ElectionCount=0; - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - } - } - } -} diff --git a/source4/nmbd/nmbd_incomingdgrams.c b/source4/nmbd/nmbd_incomingdgrams.c deleted file mode 100644 index 3000c347d8..0000000000 --- a/source4/nmbd/nmbd_incomingdgrams.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern BOOL found_lm_clients; - -#if 0 - -/* XXXX note: This function is currently unsuitable for use, as it - does not properly check that a server is in a fit state to become - a backup browser before asking it to be one. - The code is left here to be worked on at a later date. -*/ - -/**************************************************************************** -Tell a server to become a backup browser -**************************************************************************/ - -void tell_become_backup(void) -{ - struct subnet_record *subrec; - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - struct server_record *servrec; - int num_servers = 0; - int num_backups = 0; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - num_servers++; - - if (is_myname(servrec->serv.name)) - continue; - - if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER) - { - num_backups++; - continue; - } - - if (servrec->serv.type & SV_TYPE_MASTER_BROWSER) - continue; - - if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER)) - continue; - - DEBUG(3,("num servers: %d num backups: %d\n", - num_servers, num_backups)); - - /* make first server a backup server. thereafter make every - tenth server a backup server */ - if (num_backups != 0 && (num_servers+9) / num_backups > 10) - continue; - - DEBUG(2,("sending become backup to %s %s for %s\n", - servrec->serv.name, inet_ntoa(subrec->bcast_ip), - work->work_group)); - - /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ - do_announce_request(servrec->serv.name, work->work_group, - ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip); - } - } - } -} -#endif - -/******************************************************************* - Process an incoming host announcement packet. -*******************************************************************/ - -void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *announce_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *comment = buf+31; - struct work_record *work; - struct server_record *servrec; - const char *work_name; - char *source_name = dgram->source_name.name; - - START_PROFILE(host_announce); - comment[43] = 0; - - DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \ -%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),announce_name)); - - DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n", - ttl, servertype,comment)); - - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - - /* A host announcement must be sent to the name WORKGROUP<1d>. */ - if(dgram->dest_name.name_type != 0x1d) - { - DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \ -(was %02x) should be 0x1d. Allowing packet anyway.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - /* Change it so it was. */ - dgram->dest_name.name_type = 0x1d; - } - - /* For a host announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - /* - * Syntax servers version 5.1 send HostAnnounce packets to - * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> - * instead of WORKGROUP<1d> name. So to fix this we check if - * the workgroup name is our own name, and if so change it - * to be our primary workgroup name. - */ - - if(strequal(work_name, lp_netbios_name())) - work_name = lp_workgroup(); - - /* - * We are being very agressive here in adding a workgroup - * name on the basis of a host announcing itself as being - * in that workgroup. Maybe we should wait for the workgroup - * announce instead ? JRA. - */ - - work = find_workgroup_on_subnet(subrec, work_name); - - if(servertype != 0) - { - if (work ==NULL ) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } - - if((servrec = find_server_in_workgroup( work, announce_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, announce_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl( servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); - } - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(announce_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, announce_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - subrec->work_changed = True; -done: - END_PROFILE(host_announce); -} - -/******************************************************************* - Process an incoming WORKGROUP announcement packet. -*******************************************************************/ - -void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *workgroup_announce_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *master_name = buf+31; - struct work_record *work; - char *source_name = dgram->source_name.name; - - START_PROFILE(workgroup_announce); - master_name[43] = 0; - - DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \ -%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),workgroup_announce_name)); - - DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n", - ttl, servertype, master_name)); - - /* Workgroup announcements must only go to the MSBROWSE name. */ - if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) - { - DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n", - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - goto done; - } - - if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL) - goto done; - } - else - { - /* Update the workgroup death_time. */ - update_workgroup_ttl(work, ttl); - } - - if(*work->local_master_browser_name == '\0') - { - /* Set the master browser name. */ - set_workgroup_local_master_browser_name( work, master_name ); - } - - subrec->work_changed = True; -done: - END_PROFILE(workgroup_announce); -} - -/******************************************************************* - Process an incoming local master browser announcement packet. -*******************************************************************/ - -void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *server_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *comment = buf+31; - char *work_name; - struct work_record *work; - struct server_record *servrec; - char *source_name = dgram->source_name.name; - - START_PROFILE(local_master_announce); - comment[43] = 0; - - DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \ -%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),server_name)); - - DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n", - ttl, servertype, comment)); - - /* A local master announcement must be sent to the name WORKGROUP<1e>. */ - if(dgram->dest_name.name_type != 0x1e) - { - DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \ -(was %02x) should be 0x1e. Ignoring packet.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - goto done; - } - - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - - /* For a local master announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) - { - /* Don't bother adding if it's a local master release announce. */ - if(servertype == 0) - goto done; - - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } - - /* If we think we're the local master browser for this workgroup, - we should never have got this packet. We don't see our own - packets. - */ - if(AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \ -a local master browser for workgroup %s and we think we are master. Forcing election.\n", - server_name, inet_ntoa(p->ip), work_name)); - - /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when - they have become a local master browser once, they will never - stop sending local master announcements. To fix this we send - them a reset browser packet, with level 0x2 on the __SAMBA__ - name that only they should be listening to. */ - - send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip); - - /* We should demote ourself and force an election. */ - - unbecome_local_master_browser( subrec, work, True); - - /* The actual election requests are handled in - nmbd_election.c */ - goto done; - } - - /* Find the server record on this workgroup. If it doesn't exist, add it. */ - - if(servertype != 0) - { - if((servrec = find_server_in_workgroup( work, server_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, server_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl(servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); - } - - set_workgroup_local_master_browser_name( work, server_name ); - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(server_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, server_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - - subrec->work_changed = True; -done: - END_PROFILE(local_master_announce); -} - -/******************************************************************* - Process a domain master announcement frame. - Domain master browsers receive these from local masters. The Domain - master should then issue a sync with the local master, asking for - that machines local server list. -******************************************************************/ - -void process_master_browser_announce(struct subnet_record *subrec, - struct packet_struct *p,char *buf) -{ - char *local_master_name = buf; - struct work_record *work; - struct browse_cache_record *browrec; - - START_PROFILE(master_browser_announce); - local_master_name[15] = 0; - - DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n", - local_master_name, inet_ntoa(p->ip))); - - if (!lp_domain_master()) - { - DEBUG(0,("process_master_browser_announce: Not configured as domain \ -master - ignoring master announce.\n")); - goto done; - } - - if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) - { - DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n", - lp_workgroup(), subrec->subnet_name)); - goto done; - } - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - DEBUG(0,("process_master_browser_announce: Local master announce made to us from \ -%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip))); - goto done; - } - - /* Add this host as a local master browser entry on the browse lists. - This causes a sync request to be made to it at a later date. - */ - - if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) - { - /* Add it. */ - create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip); - } - else - update_browser_death_time(browrec); -done: - END_PROFILE(master_browser_announce); -} - -/******************************************************************* - Process an incoming LanMan host announcement packet. -*******************************************************************/ - -void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - uint32 servertype = IVAL(buf,1); - int osmajor=CVAL(buf,5); /* major version of node software */ - int osminor=CVAL(buf,6); /* minor version of node software */ - int ttl = SVAL(buf,7); - char *announce_name = buf+9; - struct work_record *work; - struct server_record *servrec; - const char *work_name; - char *source_name = dgram->source_name.name; - pstring comment; - char *s = buf+9; - - START_PROFILE(lm_host_announce); - s = skip_string(s,1); - StrnCpy(comment, s, 43); - - DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \ -%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),announce_name)); - - DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n", - osmajor, osminor, ttl, servertype,comment)); - - if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) - { - DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \ -originate from OS/2 Warp client. Ignoring packet.\n")); - /* Could have been from a Windows machine (with its LM Announce enabled), - or a Samba server. Then don't disrupt the current browse list. */ - goto done; - } - - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - - /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */ - if(dgram->dest_name.name_type != 0x00) - { - DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \ -(was %02x) should be 0x00. Allowing packet anyway.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - /* Change it so it was. */ - dgram->dest_name.name_type = 0x00; - } - - /* For a LanMan host announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - /* - * Syntax servers version 5.1 send HostAnnounce packets to - * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> - * instead of WORKGROUP<1d> name. So to fix this we check if - * the workgroup name is our own name, and if so change it - * to be our primary workgroup name. This code is probably - * not needed in the LanMan announce code, but it won't hurt. - */ - - if(strequal(work_name, lp_netbios_name())) - work_name = lp_workgroup(); - - /* - * We are being very agressive here in adding a workgroup - * name on the basis of a host announcing itself as being - * in that workgroup. Maybe we should wait for the workgroup - * announce instead ? JRA. - */ - - work = find_workgroup_on_subnet(subrec, work_name); - - if(servertype != 0) - { - if (work == NULL) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } - - if((servrec = find_server_in_workgroup( work, announce_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, announce_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl( servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); - } - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(announce_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, announce_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - - subrec->work_changed = True; - found_lm_clients = True; -done: - END_PROFILE(lm_host_announce); -} - -/**************************************************************************** - Send a backup list response. -*****************************************************************************/ -static void send_backup_list_response(struct subnet_record *subrec, - struct work_record *work, - struct nmb_name *send_to_name, - unsigned char max_number_requested, - uint32 token, struct in_addr sendto_ip, - int port) -{ - char outbuf[1024]; - char *p, *countptr; - unsigned int count = 0; -#if 0 - struct server_record *servrec; -#endif - - memset(outbuf,'\0',sizeof(outbuf)); - - DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n", - work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip))); - - p = outbuf; - - SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */ - p++; - - countptr = p; - p++; - - SIVAL(p,0,token); /* The sender's unique info. */ - p += 4; - - /* We always return at least one name - our own. */ - count = 1; - StrnCpy(p,lp_netbios_name(),15); - strupper(p); - p = skip_string(p,1); - - /* Look for backup browsers in this workgroup. */ - -#if 0 - /* we don't currently send become_backup requests so we should never - send any other servers names out as backups for our - workgroup. That's why this is commented out (tridge) */ - - /* - * NB. Note that the struct work_record here is not neccessarily - * attached to the subnet *subrec. - */ - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - int len = PTR_DIFF(p, outbuf); - if((sizeof(outbuf) - len) < 16) - break; - - if(count >= (unsigned int)max_number_requested) - break; - - if(strnequal(servrec->serv.name, lp_netbios_name(),15)) - continue; - - if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER)) - continue; - - StrnCpy(p, servrec->serv.name, 15); - strupper(p); - count++; - - DEBUG(5,("send_backup_list_response: Adding server %s number %d\n", - p, count)); - - p = skip_string(p,1); - } -#endif - - SCVAL(countptr, 0, count); - - DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n", - send_to_name->name, inet_ntoa(sendto_ip), count)); - - send_mailslot(True, BROWSE_MAILSLOT, - outbuf,PTR_DIFF(p,outbuf), - lp_netbios_name(), 0, - send_to_name->name,0, - sendto_ip, subrec->myip, port); -} - -/******************************************************************* - Process a send backup list request packet. - - A client sends a backup list request to ask for a list of servers on - the net that maintain server lists for a domain. A server is then - chosen from this list to send NetServerEnum commands to to list - available servers. - -********************************************************************/ - -void process_get_backup_list_request(struct subnet_record *subrec, - struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct work_record *work; - unsigned char max_number_requested = CVAL(buf,0); - uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */ - int name_type = dgram->dest_name.name_type; - char *workgroup_name = dgram->dest_name.name; - struct subnet_record *search_subrec = subrec; - - START_PROFILE(get_backup_list); - DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); - - /* We have to be a master browser, or a domain master browser - for the requested workgroup. That means it must be our - workgroup. */ - - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } - - if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \ -subnet %s.\n", workgroup_name, search_subrec->subnet_name)); - goto done; - } - - /* - * If the packet was sent to WORKGROUP<1b> instead - * of WORKGROUP<1d> then it was unicast to us a domain master - * browser. Change search subrec to unicast. - */ - - if(name_type == 0x1b) - { - /* We must be a domain master browser in order to - process this packet. */ - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ -and I am not a domain master browser.\n", workgroup_name)); - goto done; - } - - search_subrec = unicast_subnet; - } - else if (name_type == 0x1d) - { - /* We must be a local master browser in order to - process this packet. */ - - if(!AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ -and I am not a local master browser.\n", workgroup_name)); - goto done; - } - } - else - { - DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n", - name_type)); - goto done; - } - - send_backup_list_response(subrec, work, &dgram->source_name, - max_number_requested, token, p->ip, p->port); -done: - END_PROFILE(get_backup_list); -} - -/******************************************************************* - Process a reset browser state packet. - - Diagnostic packet: - 0x1 - Stop being a master browser and become a backup browser. - 0x2 - Discard browse lists, stop being a master browser, try again. - 0x4 - Stop being a master browser forever. - -******************************************************************/ - -void process_reset_browser(struct subnet_record *subrec, - struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int state = CVAL(buf,0); - struct subnet_record *sr; - - START_PROFILE(reset_browser); - DEBUG(1,("process_reset_browser: received diagnostic browser reset \ -request from %s IP %s state=0x%X\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state)); - - /* Stop being a local master browser on all our broadcast subnets. */ - if (state & 0x1) - { - for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) - { - struct work_record *work; - for (work = sr->workgrouplist; work; work = work->next) - { - if (AM_LOCAL_MASTER_BROWSER(work)) - unbecome_local_master_browser(sr, work, True); - } - } - } - - /* Discard our browse lists. */ - if (state & 0x2) - { - /* - * Calling expire_workgroups_and_servers with a -1 - * time causes all servers not marked with a PERMANENT_TTL - * on the workgroup lists to be discarded, and all - * workgroups with empty server lists to be discarded. - * This means we keep our own server names and workgroup - * as these have a PERMANENT_TTL. - */ - - expire_workgroups_and_servers(-1); - } - - /* Request to stop browsing altogether. */ - if (state & 0x4) - DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n")); - - END_PROFILE(reset_browser); -} - -/******************************************************************* - Process an announcement request packet. - We don't respond immediately, we just check it's a request for - our workgroup and then set the flag telling the announce code - in nmbd_sendannounce.c:announce_my_server_names that an - announcement is needed soon. -******************************************************************/ - -void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct work_record *work; - char *workgroup_name = dgram->dest_name.name; - - START_PROFILE(announce_request); - DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); - - /* We only send announcement requests on our workgroup. */ - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } - - if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", - workgroup_name)); - goto done; - } - - work->needannounce = True; -done: - END_PROFILE(lm_host_announce); -} - -/******************************************************************* - Process a LanMan announcement request packet. - We don't respond immediately, we just check it's a request for - our workgroup and then set the flag telling that we have found - a LanMan client (DOS or OS/2) and that we will have to start - sending LanMan announcements (unless specifically disabled - through the "lm announce" parameter in smb.conf) -******************************************************************/ - -void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - char *workgroup_name = dgram->dest_name.name; - - START_PROFILE(lm_announce_request); - DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); - - /* We only send announcement requests on our workgroup. */ - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } - - if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) - { - DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", - workgroup_name)); - goto done; - } - - found_lm_clients = True; -done: - END_PROFILE(lm_host_announce); -} diff --git a/source4/nmbd/nmbd_incomingrequests.c b/source4/nmbd/nmbd_incomingrequests.c deleted file mode 100644 index 916f7763f2..0000000000 --- a/source4/nmbd/nmbd_incomingrequests.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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. - - This file contains all the code to process NetBIOS requests coming - in on port 137. It does not deal with the code needed to service - WINS server requests, but only broadcast and unicast requests. - -*/ - -#include "includes.h" - -/**************************************************************************** -Send a name release response. -**************************************************************************/ - -static void send_name_release_response(int rcode, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REL, /* nmbd type code. */ - NMB_NAME_RELEASE_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/**************************************************************************** -Process a name release packet on a broadcast subnet. -Ignore it if it's not one of our names. -****************************************************************************/ - -void process_name_release_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr owner_ip; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec; - int rcode = 0; - - putip((char *)&owner_ip,&nmb->additional->rdata[2]); - - if(!bcast) - { - /* We should only get broadcast name release packets here. - Anyone trying to release unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_release_request: unicast name release request \ -received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); - - send_name_release_response(FMT_ERR, p); - return; - } - - DEBUG(3,("process_name_release_request: Name release on name %s, \ -subnet %s from owner IP %s\n", - nmb_namestr(&nmb->question.question_name), - subrec->subnet_name, inet_ntoa(owner_ip))); - - /* If someone is releasing a broadcast group name, just ignore it. */ - if( group && !ismyip(owner_ip) ) - return; - - /* - * Code to work around a bug in FTP OnNet software NBT implementation. - * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e> - * names and *don't set the group bit* !!!!! - */ - - if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) && - ((question->name_type == 0x0) || (question->name_type == 0x1e))) - { - DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ -group release name %s from IP %s on subnet %s with no group bit set.\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name )); - return; - } - - namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME); - - /* We only care about someone trying to release one of our names. */ - if( namerec - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - rcode = ACT_ERR; - DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \ -on subnet %s being rejected as it is one of our names.\n", - nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name)); - } - - if(rcode == 0) - return; - - /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ - send_name_release_response(rcode, p); -} - -/**************************************************************************** -Send a name registration response. -**************************************************************************/ - -static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/**************************************************************************** -Process a name refresh request on a broadcast subnet. -**************************************************************************/ - -void process_name_refresh_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - struct in_addr from_ip; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(!bcast) - { - /* We should only get broadcast name refresh packets here. - Anyone trying to refresh unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_refresh_request: unicast name registration request \ -received for name %s from IP %s on subnet %s.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - DEBUG(0,("Error - should be sent to WINS server\n")); - - send_name_registration_response(FMT_ERR, 0, p); - return; - } - - /* Just log a message. We really don't care about broadcast name - refreshes. */ - - DEBUG(3,("process_name_refresh_request: Name refresh for name %s \ -IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - -} - -/**************************************************************************** -Process a name registration request on a broadcast subnet. -**************************************************************************/ - -void process_name_registration_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = nmb->additional->ttl; - struct in_addr from_ip; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(!bcast) - { - /* We should only get broadcast name registration packets here. - Anyone trying to register unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_registration_request: unicast name registration request \ -received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - - send_name_registration_response(FMT_ERR, 0, p); - return; - } - - DEBUG(3,("process_name_registration_request: Name registration for name %s \ -IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - - /* See if the name already exists. */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * If the name being registered exists and is a WINS_PROXY_NAME - * then delete the WINS proxy name entry so we don't reply erroneously - * later to queries. - */ - - if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) - { - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - if (!group) - { - /* Unique name. */ - - if( (namerec != NULL) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) - || NAME_GROUP(namerec) ) ) - { - /* No-one can register one of Samba's names, nor can they - register a name that's a group name as a unique name */ - - send_name_registration_response(ACT_ERR, 0, p); - return; - } - else if(namerec != NULL) - { - /* Update the namelist record with the new information. */ - namerec->data.ip[0] = from_ip; - update_name_ttl(namerec, ttl); - - DEBUG(3,("process_name_registration_request: Updated name record %s \ -with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - } - else - { - /* Group name. */ - - if( (namerec != NULL) - && !NAME_GROUP(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - /* Disallow group names when we have a unique name. */ - send_name_registration_response(ACT_ERR, 0, p); - return; - } - } -} - -/**************************************************************************** -This is used to sort names for a name status into a sensible order. -We put our own names first, then in alphabetical order. -**************************************************************************/ - -static int status_compare(char *n1,char *n2) -{ - int l1,l2,l3; - - /* It's a bit tricky because the names are space padded */ - for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ; - for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ; - l3 = strlen(lp_netbios_name()); - - if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 && - (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0)) - return -1; - - if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 && - (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0)) - return 1; - - return memcmp(n1,n2,18); -} - - -/**************************************************************************** - Process a node status query - ****************************************************************************/ - -void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf, *bufend, *buf0; - int names_added,i; - struct name_record *namerec; - - DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \ -subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), - subrec->subnet_name)); - - if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, - FIND_SELF_NAME)) == 0) - { - DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \ -subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), - inet_ntoa(p->ip), subrec->subnet_name)); - - return; - } - - /* this is not an exact calculation. the 46 is for the stats buffer - and the 60 is to leave room for the header etc */ - bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60); - countptr = buf = rdata; - buf += 1; - buf0 = buf; - - names_added = 0; - - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - - while (buf < bufend) - { - if( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) - { - int name_type = namerec->name.name_type; - - if (!strequal(namerec->name.name,"*") && - !strequal(namerec->name.name,"__SAMBA__") && - (name_type < 0x1b || name_type >= 0x20 || - ques_type < 0x1b || ques_type >= 0x20 || - strequal(qname, namerec->name.name))) - { - /* Start with the name. */ - memset(buf,'\0',18); - slprintf(buf, 17, "%-15.15s",namerec->name.name); - strupper(buf); - - /* Put the name type and netbios flags in the buffer. */ - buf[15] = name_type; - set_nb_flags( &buf[16],namerec->data.nb_flags ); - buf[16] |= NB_ACTIVE; /* all our names are active */ - - buf += 18; - - names_added++; - } - } - - /* Remove duplicate names. */ - if (names_added > 1) { - qsort( buf0, names_added, 18, QSORT_CAST status_compare ); - } - - for( i=1; i < names_added ; i++ ) - { - if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) - { - names_added--; - if (names_added == i) - break; - memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); - i--; - } - } - - buf = buf0 + 18*names_added; - - namerec = (struct name_record *)ubi_trNext( namerec ); - - if (!namerec) - { - /* End of the subnet specific name list. Now - add the names on the unicast subnet . */ - struct subnet_record *uni_subrec = unicast_subnet; - - if (uni_subrec != subrec) - { - subrec = uni_subrec; - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - } - } - if (!namerec) - break; - - } - - SCVAL(countptr,0,names_added); - - /* We don't send any stats as they could be used to attack - the protocol. */ - memset(buf,'\0',46); - - buf += 46; - - /* Send a NODE STATUS RESPONSE */ - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_STATUS, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - PTR_DIFF(buf,rdata)); /* data length. */ -} - - -/*************************************************************************** -Process a name query. - -For broadcast name queries: - - - Only reply if the query is for one of YOUR names. - - NEVER send a negative response to a broadcast query. - -****************************************************************************/ - -void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - int name_type = question->name_type; - BOOL bcast = nmb->header.nm_flags.bcast; - int ttl=0; - int rcode = 0; - char *prdata = NULL; - char rdata[6]; - BOOL success = False; - struct name_record *namerec = NULL; - int reply_data_len = 0; - int i; - - DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n", - inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question))); - - /* Look up the name in the cache - if the request is a broadcast request that - came from a subnet we don't know about then search all the broadcast subnets - for a match (as we don't know what interface the request came in on). */ - - if(subrec == remote_broadcast_subnet) - namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME); - else - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* Check if it is a name that expired */ - if (namerec && - ((namerec->data.death_time != PERMANENT_TTL) && - (namerec->data.death_time < p->timestamp))) { - DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name))); - namerec = NULL; - } - - if (namerec) { - /* - * Always respond to unicast queries. - * Don't respond to broadcast queries unless the query is for - * a name we own, a Primary Domain Controller name, or a WINS_PROXY - * name with type 0 or 0x20. WINS_PROXY names are only ever added - * into the namelist if we were configured as a WINS proxy. - */ - - if (!bcast || - (bcast && ((name_type == 0x1b) || - (namerec->data.source == SELF_NAME) || - (namerec->data.source == PERMANENT_NAME) || - ((namerec->data.source == WINS_PROXY_NAME) && - ((name_type == 0) || (name_type == 0x20)))))) { - /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, - or it's a Domain Master type. */ - - /* - * If this is a WINS_PROXY_NAME, then ceck that none of the IP - * addresses we are returning is on the same broadcast subnet - * as the requesting packet. If it is then don't reply as the - * actual machine will be replying also and we don't want two - * replies to a broadcast query. - */ - - if (namerec->data.source == WINS_PROXY_NAME) { - for( i = 0; i < namerec->data.num_ips; i++) { - if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) { - DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n", - nmb_namestr(&namerec->name), subrec->subnet_name )); - return; - } - } - } - - ttl = (namerec->data.death_time != PERMANENT_TTL) ? - namerec->data.death_time - p->timestamp : lp_max_ttl(); - - /* Copy all known ip addresses into the return data. */ - /* Optimise for the common case of one IP address so - we don't need a malloc. */ - - if (namerec->data.num_ips == 1) { - prdata = rdata; - } else { - if ((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) { - DEBUG(0,("process_name_query_request: malloc fail !\n")); - return; - } - } - - for (i = 0; i < namerec->data.num_ips; i++) { - set_nb_flags(&prdata[i*6],namerec->data.nb_flags); - putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); - } - - sort_query_replies(prdata, i, p->ip); - - reply_data_len = namerec->data.num_ips * 6; - success = True; - } - } - - /* - * If a machine is broadcasting a name lookup request and we have lp_wins_proxy() - * set we should initiate a WINS query here. On success we add the resolved name - * into our namelist with a type of WINS_PROXY_NAME and then reply to the query. - */ - - if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() && - bcast && (subrec != remote_broadcast_subnet)) { - make_wins_proxy_name_query_request( subrec, p, question ); - return; - } - - if (!success && bcast) { - if(prdata != rdata) - SAFE_FREE(prdata); - return; /* Never reply with a negative response to broadcasts. */ - } - - /* - * Final check. From observation, if a unicast packet is sent - * to a non-WINS server with the recursion desired bit set - * then never send a negative response. - */ - - if(!success && !bcast && nmb->header.nm_flags.recursion_desired) { - if(prdata != rdata) - SAFE_FREE(prdata); - return; - } - - if (success) { - rcode = 0; - DEBUG(3,("OK\n")); - } else { - rcode = NAM_ERR; - DEBUG(3,("UNKNOWN\n")); - } - - /* See rfc1002.txt 4.2.13. */ - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - prdata, /* data to send. */ - reply_data_len); /* data length. */ - - if(prdata != rdata) - SAFE_FREE(prdata); -} diff --git a/source4/nmbd/nmbd_lmhosts.c b/source4/nmbd/nmbd_lmhosts.c deleted file mode 100644 index c47384c819..0000000000 --- a/source4/nmbd/nmbd_lmhosts.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Jeremy Allison 1994-1998 - - 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. - - Revision History: - - Handle lmhosts file reading. - -*/ - -#include "includes.h" - -/**************************************************************************** -Load a lmhosts file. -****************************************************************************/ -void load_lmhosts_file(char *fname) -{ - char *name; - int name_type; - struct in_addr ipaddr; - XFILE *fp = startlmhosts( fname ); - TALLOC_CTX *mem_ctx; - - if (!fp) { - DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", - fname, strerror(errno))); - return; - } - mem_ctx = talloc_init("load_lmhosts_files"); - if (!mem_ctx) { - DEBUG(2,("load_lmhosts_file: No memory to open lmhosts file %s. Error was %s\n", - fname, strerror(errno))); - return; - } - while (getlmhostsent(mem_ctx, fp, name, &name_type, &ipaddr) ) - { - struct subnet_record *subrec = NULL; - enum name_source source = LMHOSTS_NAME; - - /* We find a relevent subnet to put this entry on, then add it. */ - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) - break; - } - - /* If none match add the name to the remote_broadcast_subnet. */ - if(subrec == NULL) - subrec = remote_broadcast_subnet; - - if(name_type == -1) - { - /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ - (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - else - { - /* Add the given name type to the subnet namelist. */ - (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - } - - endlmhosts(fp); -} - -/**************************************************************************** - Find a name read from the lmhosts file. We secretly check the names on - the remote_broadcast_subnet as if the name was added to a regular broadcast - subnet it will be found by normal name query processing. -****************************************************************************/ - -BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp) -{ - struct name_record *namerec; - - *namerecp = NULL; - - if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, - FIND_ANY_NAME))==NULL) - return False; - - if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME)) - return False; - - *namerecp = namerec; - return True; -} diff --git a/source4/nmbd/nmbd_logonnames.c b/source4/nmbd/nmbd_logonnames.c deleted file mode 100644 index 40edc68800..0000000000 --- a/source4/nmbd/nmbd_logonnames.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern struct in_addr allones_ip; - -extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ - -/**************************************************************************** - Fail to become a Logon server on a subnet. - ****************************************************************************/ -static void become_logon_server_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *fail_name) -{ - struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), fail_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } - - /* Set the state back to LOGON_NONE. */ - work->log_state = LOGON_NONE; - - servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL; - - DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \ -workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); - -} - -/**************************************************************************** - Become a Logon server on a subnet. - ****************************************************************************/ - -static void become_logon_server_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *registered_name, - uint16 nb_flags, - int ttl, struct in_addr registered_ip) -{ - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_success: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL) - { - DEBUG(0,("become_logon_server_success: Error - cannot find server %s \ -in workgroup %s on subnet %s\n", - lp_netbios_name(), registered_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } - - /* Set the state in the workgroup structure. */ - work->log_state = LOGON_SRV; /* Become domain master. */ - - /* Update our server status. */ - servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER); - /* To allow Win95 policies to load we need to set type domain - controller. - */ - servrec->serv.type |= SV_TYPE_DOMAIN_CTRL; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* - * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address - * for this subnet so we will respond to queries on this name. - */ - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c); - } - - DEBUG(0,("become_logon_server_success: Samba is now a logon server \ -for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); -} - -/******************************************************************* - Become a logon server by attempting to register the WORKGROUP<1c> - group name. -******************************************************************/ - -static void become_logon_server(struct subnet_record *subrec, - struct work_record *work) -{ - DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \ -on subnet %s\n", work->work_group,subrec->subnet_name)); - - DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n", - work->work_group)); - work->log_state = LOGON_WAIT; - - register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP, - become_logon_server_success, - become_logon_server_fail, NULL); -} - -/***************************************************************************** - Add the internet group <1c> logon names by unicast and broadcast. - ****************************************************************************/ -void add_logon_names(void) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if (work && (work->log_state == LOGON_NONE)) - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - - if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "add_domain_logon_names:\n" ); - dbgtext( "Attempting to become logon server " ); - dbgtext( "for workgroup %s ", lp_workgroup() ); - dbgtext( "on subnet %s\n", subrec->subnet_name ); - } - become_logon_server(subrec, work); - } - } - } -} diff --git a/source4/nmbd/nmbd_mynames.c b/source4/nmbd/nmbd_mynames.c deleted file mode 100644 index dd66821839..0000000000 --- a/source4/nmbd/nmbd_mynames.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ - -/**************************************************************************** - Fail funtion when registering my netbios names. - **************************************************************************/ - -static void my_name_register_failed(struct subnet_record *subrec, - struct response_record *rrec, struct nmb_name *nmbname) -{ - DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); -} - - -/**************************************************************************** - Add my workgroup and my given names to one subnet - Also add the magic Samba names. - **************************************************************************/ -void register_my_workgroup_one_subnet(struct subnet_record *subrec) -{ - int i; - - struct work_record *work; - - /* Create the workgroup on the subnet. */ - if((work = create_workgroup_on_subnet(subrec, lp_workgroup(), - PERMANENT_TTL)) == NULL) { - DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \ -Exiting.\n", lp_workgroup(), subrec->subnet_name)); - return; - } - - /* Each subnet entry, except for the wins_server_subnet has - the magic Samba names. */ - add_samba_names_to_subnet(subrec); - - /* Register all our names including aliases. */ - for (i=0; my_netbios_names(i); i++) { - register_name(subrec, my_netbios_names(i),0x20,samba_nb_type, - NULL, - my_name_register_failed, NULL); - register_name(subrec, my_netbios_names(i),0x03,samba_nb_type, - NULL, - my_name_register_failed, NULL); - register_name(subrec, my_netbios_names(i),0x00,samba_nb_type, - NULL, - my_name_register_failed, NULL); - } - - /* Initiate election processing, register the workgroup names etc. */ - initiate_myworkgroup_startup(subrec, work); -} - -/******************************************************************* - Utility function to add a name to the unicast subnet, or add in - our IP address if it already exists. -******************************************************************/ - -static void insert_refresh_name_into_unicast( struct subnet_record *subrec, - struct nmb_name *nmbname, uint16 nb_type ) -{ - struct name_record *namerec; - - if (!we_are_a_wins_client()) { - insert_permanent_name_into_unicast(subrec, nmbname, nb_type); - return; - } - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) - { - /* The name needs to be created on the unicast subnet. */ - (void)add_name_to_subnet( unicast_subnet, nmbname->name, - nmbname->name_type, nb_type, - MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip); - } - else - { - /* The name already exists on the unicast subnet. Add our local - IP for the given broadcast subnet to the name. */ - add_ip_to_name_record( namerec, subrec->myip); - } -} - -/**************************************************************************** - Add my workgroup and my given names to the subnet lists. - Also add the magic Samba names. - **************************************************************************/ - -BOOL register_my_workgroup_and_names(void) -{ - struct subnet_record *subrec; - int i; - - for(subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - register_my_workgroup_one_subnet(subrec); - } - - /* We still need to add the magic Samba - names and the netbios names to the unicast subnet directly. This is - to allow unicast node status requests and queries to still work - in a broadcast only environment. */ - - add_samba_names_to_subnet(unicast_subnet); - - for (i=0; my_netbios_names(i); i++) - { - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, my_netbios_names(i),0x20); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x3); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - } - } - - /* - * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet - * also for the same reasons. - */ - - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, lp_workgroup(), 0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - - make_nmb_name(&nmbname, lp_workgroup(), 0x1e); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - } - - /* - * We need to add the Samba names to the remote broadcast subnet, - * as NT 4.x does directed broadcast requests to the *<0x0> name. - */ - add_samba_names_to_subnet(remote_broadcast_subnet); - - return True; -} - -/**************************************************************************** - Remove all the names we registered. -**************************************************************************/ -void release_wins_names(void) -{ - struct subnet_record *subrec = unicast_subnet; - struct name_record *namerec, *nextnamerec; - - for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = nextnamerec) { - nextnamerec = (struct name_record *)ubi_trNext( namerec ); - if( (namerec->data.source == SELF_NAME) - && !NAME_IS_DEREGISTERING(namerec) ) - release_name( subrec, namerec, standard_success_release, - NULL, NULL); - } -} - -/******************************************************************* - Refresh our registered names with WINS - ******************************************************************/ -void refresh_my_names(time_t t) -{ - struct name_record *namerec; - - if (wins_srv_count() < 1) return; - - for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist); - namerec; - namerec = (struct name_record *)ubi_trNext(namerec)) { - /* Each SELF name has an individual time to be refreshed. */ - if ((namerec->data.source == SELF_NAME) && - (namerec->data.refresh_time < t) && - (namerec->data.death_time != PERMANENT_TTL)) { - /* We cheat here and pretend the refresh is going to be - successful & update the refresh times. This stops - multiple refresh calls being done. We actually - deal with refresh failure in the fail_fn. - */ - if (!is_refresh_already_queued(unicast_subnet, namerec)) { - wins_refresh_name(namerec); - } - namerec->data.death_time = t + lp_max_ttl(); - namerec->data.refresh_time = t + MIN(lp_max_ttl()/2, MAX_REFRESH_TIME); - } - } -} diff --git a/source4/nmbd/nmbd_namelistdb.c b/source4/nmbd/nmbd_namelistdb.c deleted file mode 100644 index 6653cdd24b..0000000000 --- a/source4/nmbd/nmbd_namelistdb.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -uint16 samba_nb_type = 0; /* samba's NetBIOS name type */ - - -/* ************************************************************************** ** - * Set Samba's NetBIOS name type. - * ************************************************************************** ** - */ -void set_samba_nb_type(void) - { - if( lp_wins_support() || wins_srv_count() ) - samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ - else - samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ - } /* set_samba_nb_type */ - -/* ************************************************************************** ** - * Convert a NetBIOS name to upper case. - * ************************************************************************** ** - */ -static void upcase_name( struct nmb_name *target, struct nmb_name *source ) - { - int i; - - if( NULL != source ) - (void)memcpy( target, source, sizeof( struct nmb_name ) ); - - strupper( target->name ); - strupper( target->scope ); - - /* fudge... We're using a byte-by-byte compare, so we must be sure that - * unused space doesn't have garbage in it. - */ - for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) - target->name[i] = '\0'; - for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) - target->scope[i] = '\0'; - } /* upcase_name */ - -/* ************************************************************************** ** - * Add a new or overwrite an existing namelist entry. - * ************************************************************************** ** - */ -static void update_name_in_namelist( struct subnet_record *subrec, - struct name_record *namerec ) - { - struct name_record *oldrec = NULL; - - (void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); - if( oldrec ) - { - SAFE_FREE( oldrec->data.ip ); - SAFE_FREE( oldrec ); - } - } /* update_name_in_namelist */ - -/* ************************************************************************** ** - * Remove a name from the namelist. - * ************************************************************************** ** - */ -void remove_name_from_namelist( struct subnet_record *subrec, - struct name_record *namerec ) - { - (void)ubi_trRemove( subrec->namelist, namerec ); - - SAFE_FREE(namerec->data.ip); - - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); - - subrec->namelist_changed = True; - } /* remove_name_from_namelist */ - -/* ************************************************************************** ** - * Find a name in a subnet. - * ************************************************************************** ** - */ -struct name_record *find_name_on_subnet( struct subnet_record *subrec, - struct nmb_name *nmbname, - BOOL self_only ) - { - struct nmb_name uc_name[1]; - struct name_record *name_ret; - - upcase_name( uc_name, nmbname ); - name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); - if( name_ret ) - { - /* Self names only - these include permanent names. */ - if( self_only - && (name_ret->data.source != SELF_NAME) - && (name_ret->data.source != PERMANENT_NAME) ) - { - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } - DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", - subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); - return( name_ret ); - } - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } /* find_name_on_subnet */ - -/* ************************************************************************** ** - * Find a name over all known broadcast subnets. - * ************************************************************************** ** - */ -struct name_record *find_name_for_remote_broadcast_subnet( - struct nmb_name *nmbname, - BOOL self_only ) - { - struct subnet_record *subrec; - struct name_record *namerec = NULL; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) - { - if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) - break; - } - - return( namerec ); - } /* find_name_for_remote_broadcast_subnet */ - -/* ************************************************************************** ** - * Update the ttl of an entry in a subnet name list. - * ************************************************************************** ** - */ -void update_name_ttl( struct name_record *namerec, int ttl ) -{ - time_t time_now = time(NULL); - - if( namerec->data.death_time != PERMANENT_TTL ) - namerec->data.death_time = time_now + ttl; - - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); - - namerec->subnet->namelist_changed = True; -} /* update_name_ttl */ - -/* ************************************************************************** ** - * Add an entry to a subnet name list. - * ************************************************************************** ** - */ -struct name_record *add_name_to_subnet( struct subnet_record *subrec, - const char *name, - int type, - uint16 nb_flags, - int ttl, - enum name_source source, - int num_ips, - struct in_addr *iplist) -{ - struct name_record *namerec; - time_t time_now = time(NULL); - - namerec = (struct name_record *)malloc( sizeof(*namerec) ); - if( NULL == namerec ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); - return( NULL ); - } - - memset( (char *)namerec, '\0', sizeof(*namerec) ); - namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) - * num_ips ); - if( NULL == namerec->data.ip ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); - - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); - return NULL; - } - - namerec->subnet = subrec; - - make_nmb_name(&namerec->name, name, type); - upcase_name(&namerec->name, NULL ); - - /* Enter the name as active. */ - namerec->data.nb_flags = nb_flags | NB_ACTIVE; - namerec->data.wins_flags = WINS_ACTIVE; - - /* If it's our primary name, flag it as so. */ - if( strequal( my_netbios_names(0), name ) ) - namerec->data.nb_flags |= NB_PERM; - - /* Copy the IPs. */ - namerec->data.num_ips = num_ips; - memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); - - /* Data source. */ - namerec->data.source = source; - - /* Setup the death_time and refresh_time. */ - if( ttl == PERMANENT_TTL ) - namerec->data.death_time = PERMANENT_TTL; - else - namerec->data.death_time = time_now + ttl; - - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); - - /* Now add the record to the name list. */ - update_name_in_namelist( subrec, namerec ); - - DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ -ttl=%d nb_flags=%2x to subnet %s\n", - nmb_namestr( &namerec->name ), - inet_ntoa( *iplist ), - ttl, - (unsigned int)nb_flags, - subrec->subnet_name ) ); - - subrec->namelist_changed = True; - - return(namerec); -} - -/******************************************************************* - Utility function automatically called when a name refresh or register - succeeds. By definition this is a SELF_NAME (or we wouldn't be registering - it). - ******************************************************************/ - -void standard_success_register(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *nmbname, uint16 nb_flags, int ttl, - struct in_addr registered_ip) -{ - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - if( NULL == namerec ) - (void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type, - nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); - else - update_name_ttl( namerec, ttl ); -} - -/******************************************************************* - Utility function automatically called when a name refresh or register - fails. Note that this is only ever called on a broadcast subnet with - one IP address per name. This is why it can just delete the name - without enumerating the IP adresses. JRA. - ******************************************************************/ - -void standard_fail_register( struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *nmbname ) -{ - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - - DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ -on subnet %s\n", - nmb_namestr(nmbname), subrec->subnet_name) ); - - /* Remove the name from the subnet. */ - if( namerec ) - remove_name_from_namelist(subrec, namerec); -} - -/******************************************************************* - Utility function to remove an IP address from a name record. - ******************************************************************/ - -static void remove_nth_ip_in_record( struct name_record *namerec, int ind) -{ - if( ind != namerec->data.num_ips ) - memmove( (char *)(&namerec->data.ip[ind]), - (char *)(&namerec->data.ip[ind+1]), - ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); - - namerec->data.num_ips--; - namerec->subnet->namelist_changed = True; -} - -/******************************************************************* - Utility function to check if an IP address exists in a name record. - ******************************************************************/ - -BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) -{ - int i; - - for(i = 0; i < namerec->data.num_ips; i++) - if(ip_equal( namerec->data.ip[i], ip)) - return True; - - return False; -} - -/******************************************************************* - Utility function to add an IP address to a name record. - ******************************************************************/ - -void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) -{ - struct in_addr *new_list; - - /* Don't add one we already have. */ - if( find_ip_in_name_record( namerec, new_ip ) ) - return; - - new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) - * sizeof(struct in_addr) ); - if( NULL == new_list ) - { - DEBUG(0,("add_ip_to_name_record: Malloc fail !\n")); - return; - } - - memcpy( (char *)new_list, - (char *)namerec->data.ip, - namerec->data.num_ips * sizeof(struct in_addr) ); - new_list[namerec->data.num_ips] = new_ip; - - SAFE_FREE(namerec->data.ip); - namerec->data.ip = new_list; - namerec->data.num_ips += 1; - - namerec->subnet->namelist_changed = True; -} - -/******************************************************************* - Utility function to remove an IP address from a name record. - ******************************************************************/ - -void remove_ip_from_name_record( struct name_record *namerec, - struct in_addr remove_ip ) -{ - /* Try and find the requested ip address - remove it. */ - int i; - int orig_num = namerec->data.num_ips; - - for(i = 0; i < orig_num; i++) - if( ip_equal( remove_ip, namerec->data.ip[i]) ) - { - remove_nth_ip_in_record( namerec, i); - break; - } -} - -/******************************************************************* - Utility function that release_name callers can plug into as the - success function when a name release is successful. Used to save - duplication of success_function code. - ******************************************************************/ - -void standard_success_release( struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *nmbname, - struct in_addr released_ip ) -{ - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME ); - - if( namerec == NULL ) - { - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. Name was not found on subnet.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name) ); - return; - } - else - { - int orig_num = namerec->data.num_ips; - - remove_ip_from_name_record( namerec, released_ip ); - - if( namerec->data.num_ips == orig_num ) - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. This ip is not known for this name.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name ) ); - } - - if( namerec->data.num_ips == 0 ) - remove_name_from_namelist( subrec, namerec ); -} - -/******************************************************************* - Expires old names in a subnet namelist. - ******************************************************************/ - -void expire_names_on_subnet(struct subnet_record *subrec, time_t t) -{ - struct name_record *namerec; - struct name_record *next_namerec; - - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = next_namerec ) - { - next_namerec = (struct name_record *)ubi_trNext( namerec ); - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < t) ) - { - if( namerec->data.source == SELF_NAME ) - { - DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ -name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - namerec->subnet->namelist_changed = True; - continue; - } - DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name))); - - remove_name_from_namelist( subrec, namerec ); - } - } -} - -/******************************************************************* - Expires old names in all subnet namelists. - ******************************************************************/ - -void expire_names(time_t t) -{ - struct subnet_record *subrec; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - { - expire_names_on_subnet( subrec, t ); - } -} - -/**************************************************************************** - Add the magic samba names, useful for finding samba servers. - These go directly into the name list for a particular subnet, - without going through the normal registration process. - When adding them to the unicast subnet, add them as a list of - all broadcast subnet IP addresses. -**************************************************************************/ - -void add_samba_names_to_subnet( struct subnet_record *subrec ) -{ - struct in_addr *iplist = &subrec->myip; - int num_ips = 1; - - /* These names are added permanently (ttl of zero) and will NOT be - refreshed. */ - - if( (subrec == unicast_subnet) - || (subrec == wins_server_subnet) - || (subrec == remote_broadcast_subnet) ) - { - struct subnet_record *bcast_subrecs; - int i; - /* Create an IP list containing all our known subnets. */ - - num_ips = iface_count(); - iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) ); - if( NULL == iplist ) - { - DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n")); - return; - } - - for( bcast_subrecs = FIRST_SUBNET, i = 0; - bcast_subrecs; - bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) - iplist[i] = bcast_subrecs->myip; - - } - - (void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - - if(iplist != &subrec->myip) - SAFE_FREE(iplist); -} - -/**************************************************************************** - Dump the contents of the namelists on all the subnets (including unicast) - into a file. Initiated by SIGHUP - used to debug the state of the namelists. -**************************************************************************/ - -static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) -{ - struct name_record *namerec; - const char *src_type; - struct tm *tm; - int i; - - x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); - switch(namerec->data.source) - { - case LMHOSTS_NAME: - src_type = "LMHOSTS_NAME"; - break; - case WINS_PROXY_NAME: - src_type = "WINS_PROXY_NAME"; - break; - case REGISTER_NAME: - src_type = "REGISTER_NAME"; - break; - case SELF_NAME: - src_type = "SELF_NAME"; - break; - case DNS_NAME: - src_type = "DNS_NAME"; - break; - case DNSFAIL_NAME: - src_type = "DNSFAIL_NAME"; - break; - case PERMANENT_NAME: - src_type = "PERMANENT_NAME"; - break; - default: - src_type = "unknown!"; - break; - } - x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - - if(namerec->data.death_time != PERMANENT_TTL) - { - tm = localtime(&namerec->data.death_time); - x_fprintf(fp, "death_time = %s\t", asctime(tm)); - } - else - x_fprintf(fp, "death_time = PERMANENT\t"); - - if(namerec->data.refresh_time != PERMANENT_TTL) - { - tm = localtime(&namerec->data.refresh_time); - x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); - } - else - x_fprintf(fp, "refresh_time = PERMANENT\n"); - - x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); - for(i = 0; i < namerec->data.num_ips; i++) - x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); - - x_fprintf(fp, "\n\n"); - } -} - -/**************************************************************************** - Dump the contents of the namelists on all the subnets (including unicast) - into a file. Initiated by SIGHUP - used to debug the state of the namelists. -**************************************************************************/ - -void dump_all_namelists(void) -{ - XFILE *fp; - struct subnet_record *subrec; - - fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644); - - if (!fp) - { - DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n", - "namelist.debug",strerror(errno))); - return; - } - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - dump_subnet_namelist( subrec, fp ); - - if( !we_are_a_wins_client() ) - dump_subnet_namelist( unicast_subnet, fp ); - - if( remote_broadcast_subnet->namelist != NULL ) - dump_subnet_namelist( remote_broadcast_subnet, fp ); - - if( wins_server_subnet != NULL ) - dump_subnet_namelist( wins_server_subnet, fp ); - x_fclose( fp ); -} diff --git a/source4/nmbd/nmbd_namequery.c b/source4/nmbd/nmbd_namequery.c deleted file mode 100644 index 8995e9ac52..0000000000 --- a/source4/nmbd/nmbd_namequery.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/**************************************************************************** - Deal with a response packet when querying a name. -****************************************************************************/ - -static void query_name_response( struct subnet_record *subrec, - struct response_record *rrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - BOOL success = False; - struct nmb_name *question_name = - &rrec->packet->packet.nmb.question.question_name; - struct in_addr answer_ip; - - zero_ip(&answer_ip); - - /* Ensure we don't retry the query but leave the response record cleanup - to the timeout code. We may get more answer responses in which case - we should mark the name in conflict.. */ - rrec->repeat_count = 0; - - if(rrec->num_msgs == 1) - { - /* This is the first response. */ - - if(nmb->header.opcode == NMB_WACK_OPCODE) - { - /* WINS server is telling us to wait. Pretend we didn't get - the response but don't send out any more query requests. */ - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: " ); - dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) ); - dbgtext( "in querying name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } - - rrec->repeat_count = 0; - /* How long we should wait for. */ - rrec->repeat_time = p->timestamp + nmb->answers->ttl; - rrec->num_msgs--; - return; - } - else if(nmb->header.rcode != 0) - { - success = False; - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "Error code was %d.\n", nmb->header.rcode ); - } - } - else - { - if (!nmb->answers) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "IP %s ", inet_ntoa(p->ip) ); - dbgtext( "returned a success response with no answer\n" ); - return; - } - - success = True; - - putip((char *)&answer_ip,&nmb->answers->rdata[2]); - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) ); - } - - /* Interestingly, we could add these names to our namelists, and - change nmbd to a model that checked its own name cache first, - before sending out a query. This is a task for another day, though. - */ - } - } - else if( rrec->num_msgs > 1) - { - if( DEBUGLVL( 0 ) ) - { - if (nmb->answers) - putip( (char *)&answer_ip, &nmb->answers->rdata[2] ); - dbgtext( "query_name_response: " ); - dbgtext( "Multiple (%d) responses ", rrec->num_msgs ); - dbgtext( "received for a query on subnet %s ", subrec->subnet_name ); - dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) ); - dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) ); - dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) ); - } - - /* We have already called the success or fail function, so we - don't call again here. Leave the response record around in - case we get more responses. */ - - return; - } - - if(success && rrec->success_fn) - (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers); - else if( rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode); - -} - -/**************************************************************************** - Deal with a timeout when querying a name. -****************************************************************************/ - -static void query_name_timeout_response(struct subnet_record *subrec, - struct response_record *rrec) -{ - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - /* We can only fail here, never succeed. */ - BOOL failed = True; - struct nmb_name *question_name = &sent_nmb->question.question_name; - - if(rrec->num_msgs != 0) - { - /* We got at least one response, and have called the success/fail - function already. */ - - failed = False; - } - - if(failed) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_timeout_response: No response to " ); - dbgtext( "query for name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } - if(rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0); - } - - remove_response_record(subrec, rrec); -} - -/**************************************************************************** - Lookup a name on our local namelists. We check the lmhosts file first. If the - name is not there we look for the name on the given subnet. -****************************************************************************/ - -static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname, - struct name_record **namerecp) -{ - struct name_record *namerec; - - *namerecp = NULL; - - if(find_name_in_lmhosts(nmbname, namerecp)) - return True; - - if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL) - return False; - - if( NAME_IS_ACTIVE(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == LMHOSTS_NAME) ) ) - { - *namerecp = namerec; - return True; - } - return False; -} - -/**************************************************************************** - Try and query for a name. -****************************************************************************/ - -BOOL query_name(struct subnet_record *subrec, char *name, int type, - query_name_success_function success_fn, - query_name_fail_function fail_fn, - struct userdata_struct *userdata) -{ - struct nmb_name nmbname; - struct name_record *namerec; - - make_nmb_name(&nmbname, name, type); - - /* - * We need to check our local namelists first. - * It may be an magic name, lmhosts name or just - * a name we have registered. - */ - - if(query_local_namelists(subrec, &nmbname, &namerec) == True) - { - struct res_rec rrec; - int i; - - memset((char *)&rrec, '\0', sizeof(struct res_rec)); - - /* Fake up the needed res_rec just in case it's used. */ - rrec.rr_name = nmbname; - rrec.rr_type = RR_TYPE_NB; - rrec.rr_class = RR_CLASS_IN; - rrec.ttl = PERMANENT_TTL; - rrec.rdlength = namerec->data.num_ips * 6; - if(rrec.rdlength > MAX_DGRAM_SIZE) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: nmbd internal error - " ); - dbgtext( "there are %d ip addresses ", namerec->data.num_ips ); - dbgtext( "for name %s.\n", nmb_namestr(&nmbname) ); - } - return False; - } - - for( i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags ); - putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]); - } - - /* Call the success function directly. */ - if(success_fn) - (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec); - return False; - } - - if(queue_query_name( subrec, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; -} - -/**************************************************************************** - Try and query for a name from nmbd acting as a WINS server. -****************************************************************************/ - -BOOL query_name_from_wins_server(struct in_addr ip_to, - char *name, int type, - query_name_success_function success_fn, - query_name_fail_function fail_fn, - struct userdata_struct *userdata) -{ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, name, type); - - if(queue_query_name_from_wins_server( ip_to, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name_from_wins_server: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; -} diff --git a/source4/nmbd/nmbd_nameregister.c b/source4/nmbd/nmbd_nameregister.c deleted file mode 100644 index 7bf2584053..0000000000 --- a/source4/nmbd/nmbd_nameregister.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/* forward declarations */ -static void wins_next_registration(struct response_record *rrec); - - -/**************************************************************************** - Deal with a response packet when registering one of our names. -****************************************************************************/ - -static void register_name_response(struct subnet_record *subrec, - struct response_record *rrec, struct packet_struct *p) -{ - /* - * If we are registering broadcast, then getting a response is an - * error - we do not have the name. If we are registering unicast, - * then we expect to get a response. - */ - - struct nmb_packet *nmb = &p->packet.nmb; - BOOL bcast = nmb->header.nm_flags.bcast; - BOOL success = True; - struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; - struct nmb_name *answer_name = &nmb->answers->rr_name; - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - int ttl = 0; - uint16 nb_flags = 0; - struct in_addr register_ip; - fstring reg_name; - - putip(®ister_ip,&sent_nmb->additional->rdata[2]); - fstrcpy(reg_name, inet_ntoa(register_ip)); - - if (subrec == unicast_subnet) { - /* we know that this wins server is definately alive - for the moment! */ - wins_srv_alive(rrec->packet->ip, register_ip); - } - - /* Sanity check. Ensure that the answer name in the incoming packet is the - same as the requested name in the outgoing packet. */ - - if(!question_name || !answer_name) { - DEBUG(0,("register_name_response: malformed response (%s is NULL).\n", - question_name ? "question_name" : "answer_name" )); - return; - } - - if(!nmb_name_equal(question_name, answer_name)) { - DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", - nmb_namestr(answer_name), nmb_namestr(question_name))); - return; - } - - if(bcast) { - /* - * Special hack to cope with old Samba nmbd's. - * Earlier versions of Samba (up to 1.9.16p11) respond - * to a broadcast name registration of WORKGROUP<1b> when - * they should not. Hence, until these versions are gone, - * we should treat such errors as success for this particular - * case only. jallison@whistle.com. - */ - -#if 1 /* OLD_SAMBA_SERVER_HACK */ - if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), answer_name->name) && - (answer_name->name_type == 0x1b)) { - /* Pretend we did not get this. */ - rrec->num_msgs--; - - DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", - nmb_namestr(answer_name))); - return; - } -#endif /* OLD_SAMBA_SERVER_HACK */ - - /* Someone else has the name. Log the problem. */ - DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", - nmb_namestr(answer_name), - reg_name, - subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip))); - success = False; - } else { - /* Unicast - check to see if the response allows us to have the name. */ - if (nmb->header.opcode == NMB_WACK_OPCODE) { - /* WINS server is telling us to wait. Pretend we didn't get - the response but don't send out any more register requests. */ - - DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", - inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name)); - - rrec->repeat_count = 0; - /* How long we should wait for. */ - rrec->repeat_time = p->timestamp + nmb->answers->ttl; - rrec->num_msgs--; - return; - } else if (nmb->header.rcode != 0) { - /* Error code - we didn't get the name. */ - success = False; - - DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", - subrec==unicast_subnet?"WINS ":"", - inet_ntoa(p->ip), - nmb_namestr(answer_name), - reg_name, - nmb->header.rcode)); - } else { - success = True; - /* Get the data we need to pass to the success function. */ - nb_flags = get_nb_flags(nmb->answers->rdata); - ttl = nmb->answers->ttl; - - /* send off a registration for the next IP, if any */ - wins_next_registration(rrec); - } - } - - DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n", - success ? "success" : "failure", - subrec==unicast_subnet?"WINS ":"", - nmb_namestr(answer_name), - reg_name, - inet_ntoa(rrec->packet->ip))); - - if(success) { - /* Enter the registered name into the subnet name database before calling - the success function. */ - standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); - if( rrec->success_fn) - (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); - } else { - if( rrec->fail_fn) - (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); - /* Remove the name. */ - standard_fail_register( subrec, rrec, question_name); - } - - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); -} - - -/**************************************************************************** - Deal with a timeout of a WINS registration request -****************************************************************************/ -static void wins_registration_timeout(struct subnet_record *subrec, - struct response_record *rrec) -{ - struct userdata_struct *userdata = rrec->userdata; - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - struct nmb_name *nmbname = &sent_nmb->question.question_name; - struct in_addr register_ip; - fstring src_addr; - - putip(®ister_ip,&sent_nmb->additional->rdata[2]); - - fstrcpy(src_addr, inet_ntoa(register_ip)); - - DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", - inet_ntoa(rrec->packet->ip), src_addr)); - - /* mark it temporarily dead for this source address */ - wins_srv_died(rrec->packet->ip, register_ip); - - /* if we have some userdata then use that to work out what - wins server to try next */ - if (userdata) { - const char *tag = (const char *)userdata->data; - - /* try the next wins server in our failover list for - this tag */ - rrec->packet->ip = wins_srv_ip_tag(tag, register_ip); - } - - /* if we have run out of wins servers for this tag then they - must all have timed out. We treat this as *success*, not - failure, and go into our standard name refresh mode. This - copes with all the wins servers being down */ - if (wins_srv_is_dead(rrec->packet->ip, register_ip)) { - uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata); - int ttl = sent_nmb->additional->ttl; - - standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip); - if(rrec->success_fn) { - (*(register_name_success_function)rrec->success_fn)(subrec, - rrec->userdata, - nmbname, - nb_flags, - ttl, - register_ip); - } - - /* send off a registration for the next IP, if any */ - wins_next_registration(rrec); - - /* don't need to send this packet any more */ - remove_response_record(subrec, rrec); - return; - } - - /* we will be moving to the next WINS server for this group, - send it immediately */ - rrec->repeat_count = 2; - rrec->repeat_time = time(NULL) + 1; - rrec->in_expiration_processing = False; - - DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n", - nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip))); - - /* notice that we don't remove the response record. This keeps - us trying to register with each of our failover wins servers */ -} - - -/**************************************************************************** - Deal with a timeout when registering one of our names. -****************************************************************************/ - -static void register_name_timeout_response(struct subnet_record *subrec, - struct response_record *rrec) -{ - /* - * If we are registering unicast, then NOT getting a response is an - * error - we do not have the name. If we are registering broadcast, - * then we don't expect to get a response. - */ - - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - BOOL bcast = sent_nmb->header.nm_flags.bcast; - BOOL success = False; - struct nmb_name *question_name = &sent_nmb->question.question_name; - uint16 nb_flags = 0; - int ttl = 0; - struct in_addr registered_ip; - - if (bcast) { - if(rrec->num_msgs == 0) { - /* Not receiving a message is success for broadcast registration. */ - success = True; - - /* Pull the success values from the original request packet. */ - nb_flags = get_nb_flags(sent_nmb->additional->rdata); - ttl = sent_nmb->additional->ttl; - putip(®istered_ip,&sent_nmb->additional->rdata[2]); - } - } else { - /* wins timeouts are special */ - wins_registration_timeout(subrec, rrec); - return; - } - - DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n", - success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name)); - if(success) { - /* Enter the registered name into the subnet name database before calling - the success function. */ - standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); - if( rrec->success_fn) - (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); - } else { - if( rrec->fail_fn) - (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); - /* Remove the name. */ - standard_fail_register( subrec, rrec, question_name); - } - - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); -} - - -/**************************************************************************** -initiate one multi-homed name registration packet -****************************************************************************/ -static void multihomed_register_one(struct nmb_name *nmbname, - uint16 nb_flags, - register_name_success_function success_fn, - register_name_fail_function fail_fn, - struct in_addr ip, - const char *tag) -{ - struct userdata_struct *userdata; - struct in_addr wins_ip = wins_srv_ip_tag(tag, ip); - fstring ip_str; - - userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1); - if (!userdata) { - DEBUG(0,("Failed to allocate userdata structure!\n")); - return; - } - ZERO_STRUCTP(userdata); - userdata->userdata_len = strlen(tag) + 1; - strlcpy(userdata->data, tag, userdata->userdata_len); - - fstrcpy(ip_str, inet_ntoa(ip)); - - DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n", - nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag)); - - if (queue_register_multihomed_name(unicast_subnet, - register_name_response, - register_name_timeout_response, - success_fn, - fail_fn, - userdata, - nmbname, - nb_flags, - ip, - wins_ip) == NULL) { - DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n", - nmb_namestr(nmbname), inet_ntoa(ip))); - } - - free(userdata); -} - - -/**************************************************************************** -we have finished the registration of one IP and need to see if we have -any more IPs left to register with this group of wins server for this name -****************************************************************************/ -static void wins_next_registration(struct response_record *rrec) -{ - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - struct nmb_name *nmbname = &sent_nmb->question.question_name; - uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata); - struct userdata_struct *userdata = rrec->userdata; - const char *tag; - struct in_addr last_ip; - struct subnet_record *subrec; - - putip(&last_ip,&sent_nmb->additional->rdata[2]); - - if (!userdata) { - /* it wasn't multi-homed */ - return; - } - - tag = (const char *)userdata->data; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { - if (ip_equal(last_ip, subrec->myip)) { - subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec); - break; - } - } - - if (!subrec) { - /* no more to do! */ - return; - } - - switch (sent_nmb->header.opcode) { - case NMB_NAME_MULTIHOMED_REG_OPCODE: - multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag); - break; - case NMB_NAME_REFRESH_OPCODE_8: - queue_wins_refresh(nmbname, - register_name_response, - register_name_timeout_response, - nb_flags, subrec->myip, tag); - break; - } -} - -/**************************************************************************** - Try and register one of our names on the unicast subnet - multihomed. -****************************************************************************/ -static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, - register_name_success_function success_fn, - register_name_fail_function fail_fn) -{ - /* - If we are adding a group name, we just send multiple - register name packets to the WINS server (this is an - internet group name. - - If we are adding a unique name, We need first to add - our names to the unicast subnet namelist. This is - because when a WINS server receives a multihomed - registration request, the first thing it does is to - send a name query to the registering machine, to see - if it has put the name in it's local namelist. - We need the name there so the query response code in - nmbd_incomingrequests.c will find it. - - We are adding this name prematurely (we don't really - have it yet), but as this is on the unicast subnet - only we will get away with this (only the WINS server - will ever query names from us on this subnet). - */ - int num_ips=0; - int i, t; - struct subnet_record *subrec; - char **wins_tags; - struct in_addr *ip_list; - - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) - num_ips++; - - if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL) { - DEBUG(0,("multihomed_register_name: malloc fail !\n")); - return; - } - - for (subrec = FIRST_SUBNET, i = 0; - subrec; - subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) { - ip_list[i] = subrec->myip; - } - - add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type, - nb_flags, lp_max_ttl(), SELF_NAME, - num_ips, ip_list); - - /* get the list of wins tags - we try to register for each of them */ - wins_tags = wins_srv_tags(); - - /* Now try and register the name for each wins tag. Note that - at this point we only register our first IP with each wins - group. We will register the rest from - wins_next_registration() when we get the reply for this - one. That follows the way W2K does things (tridge) - */ - for (t=0; wins_tags && wins_tags[t]; t++) { - multihomed_register_one(nmbname, nb_flags, - success_fn, fail_fn, - ip_list[0], - wins_tags[t]); - } - - wins_srv_tags_free(wins_tags); - - SAFE_FREE(ip_list); -} - - -/**************************************************************************** - Try and register one of our names. -****************************************************************************/ -void register_name(struct subnet_record *subrec, - const char *name, int type, uint16 nb_flags, - register_name_success_function success_fn, - register_name_fail_function fail_fn, - struct userdata_struct *userdata) -{ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, name, type); - - /* Always set the NB_ACTIVE flag on the name we are - registering. Doesn't make sense without it. - */ - - nb_flags |= NB_ACTIVE; - - if (subrec == unicast_subnet) { - /* we now always do multi-homed registration if we are - registering to a WINS server. This copes much - better with complex WINS setups */ - multihomed_register_name(&nmbname, nb_flags, - success_fn, fail_fn); - return; - } - - if (queue_register_name(subrec, - register_name_response, - register_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname, - nb_flags) == NULL) { - DEBUG(0,("register_name: Failed to send packet trying to register name %s\n", - nmb_namestr(&nmbname))); - } -} - - -/**************************************************************************** - Try and refresh one of our names. This is *only* called for WINS refresh -****************************************************************************/ -void wins_refresh_name(struct name_record *namerec) -{ - int t; - char **wins_tags; - - /* get the list of wins tags - we try to refresh for each of them */ - wins_tags = wins_srv_tags(); - - for (t=0; wins_tags && wins_tags[t]; t++) { - queue_wins_refresh(&namerec->name, - register_name_response, - register_name_timeout_response, - namerec->data.nb_flags, - namerec->data.ip[0], wins_tags[t]); - } - - wins_srv_tags_free(wins_tags); -} diff --git a/source4/nmbd/nmbd_namerelease.c b/source4/nmbd/nmbd_namerelease.c deleted file mode 100644 index 0611ca9323..0000000000 --- a/source4/nmbd/nmbd_namerelease.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/**************************************************************************** - Deal with a response packet when releasing one of our names. -****************************************************************************/ - -static void release_name_response(struct subnet_record *subrec, - struct response_record *rrec, struct packet_struct *p) -{ - /* - * If we are releasing broadcast, then getting a response is an - * error. If we are releasing unicast, then we expect to get a response. - */ - struct nmb_packet *nmb = &p->packet.nmb; - BOOL bcast = nmb->header.nm_flags.bcast; - BOOL success = True; - struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; - struct nmb_name *answer_name = &nmb->answers->rr_name; - struct in_addr released_ip; - - /* Sanity check. Ensure that the answer name in the incoming packet is the - same as the requested name in the outgoing packet. */ - if (!nmb_name_equal(question_name, answer_name)) { - DEBUG(0,("release_name_response: Answer name %s differs from question name %s.\n", - nmb_namestr(answer_name), nmb_namestr(question_name))); - return; - } - - if (bcast) { - /* Someone sent a response to a bcast release? ignore it. */ - return; - } - - /* Unicast - check to see if the response allows us to release the name. */ - if (nmb->header.rcode != 0) { - /* Error code - we were told not to release the name ! What now ! */ - success = False; - - DEBUG(0,("release_name_response: WINS server at IP %s rejected our \ -name release of name %s with error code %d.\n", - inet_ntoa(p->ip), - nmb_namestr(answer_name), nmb->header.rcode)); - } else if (nmb->header.opcode == NMB_WACK_OPCODE) { - /* WINS server is telling us to wait. Pretend we didn't get - the response but don't send out any more release requests. */ - - DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \ -name %s on subnet %s.\n", - inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->subnet_name)); - - rrec->repeat_count = 0; - /* How long we should wait for. */ - rrec->repeat_time = p->timestamp + nmb->answers->ttl; - rrec->num_msgs--; - return; - } - - DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n", - success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name)); - if (success) { - putip((char*)&released_ip ,&nmb->answers->rdata[2]); - - if(rrec->success_fn) - (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip); - standard_success_release( subrec, rrec->userdata, answer_name, released_ip); - } else { - /* We have no standard_fail_release - maybe we should add one ? */ - if (rrec->fail_fn) { - (*(release_name_fail_function)rrec->fail_fn)(subrec, rrec, answer_name); - } - } - - remove_response_record(subrec, rrec); -} - -/**************************************************************************** - Deal with a timeout when releasing one of our names. -****************************************************************************/ - -static void release_name_timeout_response(struct subnet_record *subrec, - struct response_record *rrec) -{ - /* a release is *always* considered to be successful when it - times out. This doesn't cause problems as if a WINS server - doesn't respond and someone else wants the name then the - normal WACK/name query from the WINS server will cope */ - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - BOOL bcast = sent_nmb->header.nm_flags.bcast; - struct nmb_name *question_name = &sent_nmb->question.question_name; - struct in_addr released_ip; - - /* Get the ip address we were trying to release. */ - putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]); - - if (!bcast) { - /* mark the WINS server temporarily dead */ - wins_srv_died(rrec->packet->ip, released_ip); - } - - DEBUG(5,("release_name_timeout_response: success in releasing name %s on subnet %s.\n", - nmb_namestr(question_name), subrec->subnet_name)); - - if (rrec->success_fn) { - (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip); - } - - standard_success_release( subrec, rrec->userdata, question_name, released_ip); - remove_response_record(subrec, rrec); -} - - -/* - when releasing a name with WINS we need to send the release to each of - the WINS groups -*/ -static void wins_release_name(struct name_record *namerec, - release_name_success_function success_fn, - release_name_fail_function fail_fn, - struct userdata_struct *userdata) -{ - int t, i; - char **wins_tags; - - /* get the list of wins tags - we try to release for each of them */ - wins_tags = wins_srv_tags(); - - for (t=0;wins_tags && wins_tags[t]; t++) { - for (i = 0; i < namerec->data.num_ips; i++) { - struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.ip[i]); - - BOOL last_one = ((i==namerec->data.num_ips - 1) && !wins_tags[t+1]); - if (queue_release_name(unicast_subnet, - release_name_response, - release_name_timeout_response, - last_one?success_fn : NULL, - last_one? fail_fn : NULL, - last_one? userdata : NULL, - &namerec->name, - namerec->data.nb_flags, - namerec->data.ip[i], - wins_ip) == NULL) { - DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n", - nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) )); - } - } - } - - wins_srv_tags_free(wins_tags); -} - - -/**************************************************************************** - Try and release one of our names. -****************************************************************************/ - -void release_name(struct subnet_record *subrec, struct name_record *namerec, - release_name_success_function success_fn, - release_name_fail_function fail_fn, - struct userdata_struct *userdata) -{ - int i; - - /* Ensure it's a SELF name, and in the ACTIVE state. */ - if ((namerec->data.source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) { - DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n", - nmb_namestr(&namerec->name), subrec->subnet_name, namerec->data.source)); - return; - } - - /* Set the name into the deregistering state. */ - namerec->data.nb_flags |= NB_DEREG; - - /* wins releases are a bit different */ - if (subrec == unicast_subnet) { - wins_release_name(namerec, success_fn, fail_fn, userdata); - return; - } - - /* - * Go through and release the name for all known ip addresses. - * Only call the success/fail function on the last one (it should - * only be done once). - */ - for (i = 0; i < namerec->data.num_ips; i++) { - if (queue_release_name(subrec, - release_name_response, - release_name_timeout_response, - (i == (namerec->data.num_ips - 1)) ? success_fn : NULL, - (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL, - (i == (namerec->data.num_ips - 1)) ? userdata : NULL, - &namerec->name, - namerec->data.nb_flags, - namerec->data.ip[i], - subrec->bcast_ip) == NULL) { - DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n", - nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) )); - } - } -} diff --git a/source4/nmbd/nmbd_nodestatus.c b/source4/nmbd/nmbd_nodestatus.c deleted file mode 100644 index 993e4d9d17..0000000000 --- a/source4/nmbd/nmbd_nodestatus.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/**************************************************************************** - Deal with a successful node status response. -****************************************************************************/ -static void node_status_response(struct subnet_record *subrec, - struct response_record *rrec, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; - struct nmb_name *answer_name = &nmb->answers->rr_name; - - /* Sanity check. Ensure that the answer name in the incoming packet is the - same as the requested name in the outgoing packet. */ - - if(!nmb_name_equal(question_name, answer_name)) - { - DEBUG(0,("node_status_response: Answer name %s differs from question \ -name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); - return; - } - - DEBUG(5,("node_status_response: response from name %s on subnet %s.\n", - nmb_namestr(answer_name), subrec->subnet_name)); - - /* Just send the whole answer resource record for the success function - to parse. */ - if(rrec->success_fn) - (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip); - - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); -} - -/**************************************************************************** - Deal with a timeout when requesting a node status. -****************************************************************************/ -static void node_status_timeout_response(struct subnet_record *subrec, - struct response_record *rrec) -{ - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - struct nmb_name *question_name = &sent_nmb->question.question_name; - - DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n", - nmb_namestr(question_name), subrec->subnet_name)); - - if( rrec->fail_fn) - (*rrec->fail_fn)(subrec, rrec); - - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); -} - -/**************************************************************************** - Try and do a node status to a name - given the name & IP address. -****************************************************************************/ - -BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname, - struct in_addr send_ip, node_status_success_function success_fn, - node_status_fail_function fail_fn, struct userdata_struct *userdata) -{ - if(queue_node_status( subrec, - node_status_response, node_status_timeout_response, - success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) - { - DEBUG(0,("node_status: Failed to send packet trying to get node status for \ -name %s, IP address %s\n", nmb_namestr(nmbname), inet_ntoa(send_ip))); - return True; - } - return False; -} diff --git a/source4/nmbd/nmbd_packets.c b/source4/nmbd/nmbd_packets.c deleted file mode 100644 index 6ee13812dc..0000000000 --- a/source4/nmbd/nmbd_packets.c +++ /dev/null @@ -1,2013 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern int ClientNMB; -extern int ClientDGRAM; -extern int global_nmb_port; - -extern int num_response_packets; - -extern struct in_addr loopback_ip; - -static void queue_packet(struct packet_struct *packet); - -BOOL rescan_listen_set = False; - - -/******************************************************************* - The global packet linked-list. Incoming entries are - added to the end of this list. It is supposed to remain fairly - short so we won't bother with an end pointer. -******************************************************************/ - -static struct packet_struct *packet_queue = NULL; - -/*************************************************************************** -Utility function to find the specific fd to send a packet out on. -**************************************************************************/ - -static int find_subnet_fd_for_address( struct in_addr local_ip ) -{ - struct subnet_record *subrec; - - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->nmb_sock; - - return ClientNMB; -} - -/*************************************************************************** -Utility function to find the specific fd to send a mailslot packet out on. -**************************************************************************/ - -static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip ) -{ - struct subnet_record *subrec; - - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->dgram_sock; - - return ClientDGRAM; -} - -/*************************************************************************** -Get/Set problematic nb_flags as network byte order 16 bit int. -**************************************************************************/ - -uint16 get_nb_flags(char *buf) -{ - return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK); -} - -void set_nb_flags(char *buf, uint16 nb_flags) -{ - *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF); - *buf = '\0'; -} - -/*************************************************************************** -Dumps out the browse packet data. -**************************************************************************/ - -static void debug_browse_data(char *outbuf, int len) -{ - int i,j; - - DEBUG( 4, ( "debug_browse_data():\n" ) ); - for (i = 0; i < len; i+= 16) - { - DEBUGADD( 4, ( "%3x char ", i ) ); - - for (j = 0; j < 16; j++) - { - unsigned char x; - if (i+j >= len) - break; - - x = outbuf[i+j]; - if (x < 32 || x > 127) - x = '.'; - - DEBUGADD( 4, ( "%c", x ) ); - } - - DEBUGADD( 4, ( "%*s hex", 16-j, "" ) ); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) - break; - DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) ); - } - - DEBUGADD( 4, ("\n") ); - } -} - -/*************************************************************************** - Generates the unique transaction identifier -**************************************************************************/ - -static uint16 name_trn_id=0; - -static uint16 generate_name_trn_id(void) -{ - - if (!name_trn_id) - { - name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); - } - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; - return name_trn_id; -} - -/*************************************************************************** - Either loops back or sends out a completed NetBIOS packet. -**************************************************************************/ - -static BOOL send_netbios_packet(struct packet_struct *p) -{ - BOOL loopback_this_packet = False; - - /* Check if we are sending to or from ourselves as a WINS server. */ - if(ismyip(p->ip) && (p->port == global_nmb_port)) - loopback_this_packet = True; - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(p)) == NULL) - return False; - queue_packet(lo_packet); - } - else if (!send_packet(p)) - { - DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n", - inet_ntoa(p->ip),p->port)); - return False; - } - - return True; -} - -/*************************************************************************** - Sets up the common elements of an outgoing NetBIOS packet. - - Note: do not attempt to rationalise whether rec_des should be set or not - in a particular situation. Just follow rfc_1002 or look at examples from WinXX. - It does NOT follow the rule that requests to the wins server always have - rec_des true. See for example name releases and refreshes -**************************************************************************/ - -static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmbname, - BOOL bcast, BOOL rec_des, - struct in_addr to_ip) -{ - struct packet_struct *packet = NULL; - struct nmb_packet *nmb = NULL; - - /* Allocate the packet_struct we will return. */ - if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) - { - DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n")); - return NULL; - } - - memset((char *)packet,'\0',sizeof(*packet)); - - nmb = &packet->packet.nmb; - - nmb->header.name_trn_id = generate_name_trn_id(); - nmb->header.response = False; - nmb->header.nm_flags.recursion_desired = rec_des; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - nmb->header.nm_flags.bcast = bcast; - - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - - nmb->question.question_name = *nmbname; - nmb->question.question_type = QUESTION_TYPE_NB_QUERY; - nmb->question.question_class = QUESTION_CLASS_IN; - - packet->ip = to_ip; - packet->port = NMB_PORT; - packet->fd = ClientNMB; - packet->timestamp = time(NULL); - packet->packet_type = NMB_PACKET; - packet->locked = False; - - return packet; /* Caller must free. */ -} - -/*************************************************************************** - Sets up the common elements of register, refresh or release packet. -**************************************************************************/ - -static BOOL create_and_init_additional_record(struct packet_struct *packet, - uint16 nb_flags, - struct in_addr *register_ip) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - if((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) { - DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n")); - return False; - } - - memset((char *)nmb->additional,'\0',sizeof(struct res_rec)); - - nmb->additional->rr_name = nmb->question.question_name; - nmb->additional->rr_type = RR_TYPE_NB; - nmb->additional->rr_class = RR_CLASS_IN; - - /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */ - if (nmb->header.nm_flags.bcast) - nmb->additional->ttl = PERMANENT_TTL; - else - nmb->additional->ttl = lp_max_ttl(); - - nmb->additional->rdlength = 6; - - set_nb_flags(nmb->additional->rdata,nb_flags); - - /* Set the address for the name we are registering. */ - putip(&nmb->additional->rdata[2], register_ip); - - /* - it turns out that Jeremys code was correct, we are supposed - to send registrations from the IP we are registering. The - trick is what to do on timeouts! When we send on a - non-routable IP then the reply will timeout, and we should - treat this as success, not failure. That means we go into - our standard refresh cycle for that name which copes nicely - with disconnected networks. - */ - packet->fd = find_subnet_fd_for_address(*register_ip); - - return True; -} - -/*************************************************************************** - Sends out a name query. -**************************************************************************/ - -static BOOL initiate_name_query_packet( struct packet_struct *packet) -{ - struct nmb_packet *nmb = NULL; - - nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; - - nmb->header.nm_flags.recursion_desired = True; - - DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a name query - from a WINS server. -**************************************************************************/ - -static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *packet) -{ - struct nmb_packet *nmb = NULL; - - nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; - - nmb->header.nm_flags.recursion_desired = False; - - DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a name register. -**************************************************************************/ - -static BOOL initiate_name_register_packet( struct packet_struct *packet, - uint16 nb_flags, struct in_addr *register_ip) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_REG_OPCODE; - nmb->header.arcount = 1; - - nmb->header.nm_flags.recursion_desired = True; - - if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) - return False; - - DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a multihomed name register. -**************************************************************************/ - -static BOOL initiate_multihomed_name_register_packet(struct packet_struct *packet, - uint16 nb_flags, struct in_addr *register_ip) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - fstring second_ip_buf; - - fstrcpy(second_ip_buf, inet_ntoa(packet->ip)); - - nmb->header.opcode = NMB_NAME_MULTIHOMED_REG_OPCODE; - nmb->header.arcount = 1; - - nmb->header.nm_flags.recursion_desired = True; - - if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) - return False; - - DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \ -for name %s IP %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip), - BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf )); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a name refresh. -**************************************************************************/ - -static BOOL initiate_name_refresh_packet( struct packet_struct *packet, - uint16 nb_flags, struct in_addr *refresh_ip) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8; - nmb->header.arcount = 1; - - nmb->header.nm_flags.recursion_desired = False; - - if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False) - return False; - - DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a name release. -**************************************************************************/ - -static BOOL initiate_name_release_packet( struct packet_struct *packet, - uint16 nb_flags, struct in_addr *release_ip) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; - nmb->header.arcount = 1; - - nmb->header.nm_flags.recursion_desired = False; - - if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) - return False; - - DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/*************************************************************************** - Sends out a node status. -**************************************************************************/ - -static BOOL initiate_node_status_packet( struct packet_struct *packet ) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; - - nmb->header.nm_flags.recursion_desired = False; - - nmb->question.question_type = QUESTION_TYPE_NB_STATUS; - - DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", - nmb_namestr(&nmb->question.question_name), - inet_ntoa(packet->ip))); - - return send_netbios_packet( packet ); -} - -/**************************************************************************** - Simplification functions for queuing standard packets. - These should be the only publicly callable functions for sending - out packets. -****************************************************************************/ - -/**************************************************************************** - Assertion - we should never be sending nmbd packets on the remote - broadcast subnet. -****************************************************************************/ - -static BOOL assert_check_subnet(struct subnet_record *subrec) -{ - if( subrec == remote_broadcast_subnet) - { - DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \ -This is a bug.\n")); - return True; - } - return False; -} - -/**************************************************************************** - Queue a register name packet to the broadcast address of a subnet. -****************************************************************************/ - -struct response_record *queue_register_name( struct subnet_record *subrec, - response_function resp_fn, - timeout_response_function timeout_fn, - register_name_success_function success_fn, - register_name_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname, - uint16 nb_flags) -{ - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - /* note that all name registration requests have RD set (rfc1002 - - section 4.2.2 */ - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, - subrec->bcast_ip)) == NULL) - return NULL; - - if(initiate_name_register_packet( p, nb_flags, - iface_ip(subrec->bcast_ip)) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} - - -/**************************************************************************** - Queue a refresh name packet to the broadcast address of a subnet. -****************************************************************************/ -void queue_wins_refresh(struct nmb_name *nmbname, - response_function resp_fn, - timeout_response_function timeout_fn, - uint16 nb_flags, - struct in_addr refresh_ip, - const char *tag) -{ - struct packet_struct *p; - struct response_record *rrec; - struct in_addr wins_ip; - struct userdata_struct *userdata; - fstring ip_str; - - wins_ip = wins_srv_ip_tag(tag, refresh_ip); - - if ((p = create_and_init_netbios_packet(nmbname, False, False, wins_ip)) == NULL) { - return; - } - - if (!initiate_name_refresh_packet(p, nb_flags, &refresh_ip)) { - p->locked = False; - free_packet(p); - return; - } - - fstrcpy(ip_str, inet_ntoa(refresh_ip)); - - DEBUG(6,("Refreshing name %s IP %s with WINS server %s using tag '%s'\n", - nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag)); - - userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1); - if (!userdata) { - DEBUG(0,("Failed to allocate userdata structure!\n")); - return; - } - ZERO_STRUCTP(userdata); - userdata->userdata_len = strlen(tag) + 1; - strlcpy(userdata->data, tag, userdata->userdata_len); - - if ((rrec = make_response_record(unicast_subnet, - p, - resp_fn, timeout_fn, - NULL, - NULL, - userdata)) == NULL) { - p->locked = False; - free_packet(p); - return; - } - - free(userdata); - - /* we don't want to repeat refresh packets */ - rrec->repeat_count = 0; -} - - -/**************************************************************************** - Queue a multihomed register name packet to a given WINS server IP -****************************************************************************/ - -struct response_record *queue_register_multihomed_name( struct subnet_record *subrec, - response_function resp_fn, - timeout_response_function timeout_fn, - register_name_success_function success_fn, - register_name_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname, - uint16 nb_flags, - struct in_addr register_ip, - struct in_addr wins_ip) -{ - struct packet_struct *p; - struct response_record *rrec; - BOOL ret; - - /* Sanity check. */ - if(subrec != unicast_subnet) { - DEBUG(0,("queue_register_multihomed_name: should only be done on \ -unicast subnet. subnet is %s\n.", subrec->subnet_name )); - return NULL; - } - - if(assert_check_subnet(subrec)) - return NULL; - - if ((p = create_and_init_netbios_packet(nmbname, False, True, wins_ip)) == NULL) - return NULL; - - if (nb_flags & NB_GROUP) - ret = initiate_name_register_packet( p, nb_flags, ®ister_ip); - else - ret = initiate_multihomed_name_register_packet(p, nb_flags, ®ister_ip); - - if (ret == False) { - p->locked = False; - free_packet(p); - return NULL; - } - - if ((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} - -/**************************************************************************** - Queue a release name packet to the broadcast address of a subnet. -****************************************************************************/ - -struct response_record *queue_release_name( struct subnet_record *subrec, - response_function resp_fn, - timeout_response_function timeout_fn, - release_name_success_function success_fn, - release_name_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname, - uint16 nb_flags, - struct in_addr release_ip, - struct in_addr dest_ip) -{ - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, - dest_ip)) == NULL) - return NULL; - - if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - /* - * For a broadcast release packet, only send once. - * This will cause us to remove the name asap. JRA. - */ - - if (subrec != unicast_subnet) { - rrec->repeat_count = 0; - rrec->repeat_time = 0; - } - - return rrec; -} - -/**************************************************************************** - Queue a query name packet to the broadcast address of a subnet. -****************************************************************************/ - -struct response_record *queue_query_name( struct subnet_record *subrec, - response_function resp_fn, - timeout_response_function timeout_fn, - query_name_success_function success_fn, - query_name_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname) -{ - struct packet_struct *p; - struct response_record *rrec; - struct in_addr to_ip; - - if(assert_check_subnet(subrec)) - return NULL; - - to_ip = subrec->bcast_ip; - - /* queries to the WINS server turn up here as queries to IP 0.0.0.0 - These need to be handled a bit differently */ - if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { - /* what we really need to do is loop over each of our wins - * servers and wins server tags here, but that just doesn't - * fit our architecture at the moment (userdata may already - * be used when we get here). For now we just query the first - * active wins server on the first tag. */ - char **tags = wins_srv_tags(); - if (!tags) { - return NULL; - } - to_ip = wins_srv_ip_tag(tags[0], to_ip); - wins_srv_tags_free(tags); - } - - if(( p = create_and_init_netbios_packet(nmbname, - (subrec != unicast_subnet), - (subrec == unicast_subnet), - to_ip)) == NULL) - return NULL; - - if(lp_bind_interfaces_only()) { - int i; - - DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); - for(i = 0; i < iface_count(); i++) { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) { - DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); - continue; - } - - if (ip_equal(*ifip,loopback_ip)) { - DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); - continue; - } - - DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); - p->fd = find_subnet_fd_for_address( *ifip ); - break; - } - } - - if(initiate_name_query_packet( p ) == False) { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} - -/**************************************************************************** - Queue a query name packet to a given address from the WINS subnet. -****************************************************************************/ - -struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip, - response_function resp_fn, - timeout_response_function timeout_fn, - query_name_success_function success_fn, - query_name_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname) -{ - struct packet_struct *p; - struct response_record *rrec; - - if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) - return NULL; - - if(initiate_name_query_packet_from_wins_server( p ) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(wins_server_subnet, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} - -/**************************************************************************** - Queue a node status packet to a given name and address. -****************************************************************************/ - -struct response_record *queue_node_status( struct subnet_record *subrec, - response_function resp_fn, - timeout_response_function timeout_fn, - node_status_success_function success_fn, - node_status_fail_function fail_fn, - struct userdata_struct *userdata, - struct nmb_name *nmbname, - struct in_addr send_ip) -{ - struct packet_struct *p; - struct response_record *rrec; - - /* Sanity check. */ - if(subrec != unicast_subnet) - { - DEBUG(0,("queue_register_multihomed_name: should only be done on \ -unicast subnet. subnet is %s\n.", subrec->subnet_name )); - return NULL; - } - - if(assert_check_subnet(subrec)) - return NULL; - - if(( p = create_and_init_netbios_packet(nmbname, False, False, - send_ip)) == NULL) - return NULL; - - if(initiate_node_status_packet(p) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} - -/**************************************************************************** - Reply to a netbios name packet. see rfc1002.txt -****************************************************************************/ - -void reply_netbios_packet(struct packet_struct *orig_packet, - int rcode, enum netbios_reply_type_code rcv_code, int opcode, - int ttl, char *data,int len) -{ - struct packet_struct packet; - struct nmb_packet *nmb = NULL; - struct res_rec answers; - struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; - BOOL loopback_this_packet = False; - const char *packet_type = "unknown"; - - /* Check if we are sending to or from ourselves. */ - if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) - loopback_this_packet = True; - - nmb = &packet.packet.nmb; - - /* Do a partial copy of the packet. We clear the locked flag and - the resource record pointers. */ - packet = *orig_packet; /* Full structure copy. */ - packet.locked = False; - nmb->answers = NULL; - nmb->nsrecs = NULL; - nmb->additional = NULL; - - switch (rcv_code) - { - case NMB_STATUS: - { - packet_type = "nmb_status"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_QUERY: - { - packet_type = "nmb_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REG: - case NMB_REG_REFRESH: - { - packet_type = "nmb_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REL: - { - packet_type = "nmb_rel"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_WAIT_ACK: - { - packet_type = "nmb_wack"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case WINS_REG: - { - packet_type = "wins_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case WINS_QUERY: - { - packet_type = "wins_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - - default: - { - DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip))); - - return; - } - } - - DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \ -for id %hu\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); - - nmb->header.name_trn_id = orig_nmb->header.name_trn_id; - nmb->header.opcode = opcode; - nmb->header.response = True; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = True; - - nmb->header.rcode = rcode; - nmb->header.qdcount = 0; - nmb->header.ancount = 1; - nmb->header.nscount = 0; - nmb->header.arcount = 0; - - memset((char*)&nmb->question,'\0',sizeof(nmb->question)); - - nmb->answers = &answers; - memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); - - nmb->answers->rr_name = orig_nmb->question.question_name; - nmb->answers->rr_type = orig_nmb->question.question_type; - nmb->answers->rr_class = orig_nmb->question.question_class; - nmb->answers->ttl = ttl; - - if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } - - packet.packet_type = NMB_PACKET; - /* Ensure we send out on the same fd that the original - packet came in on to give the correct source IP address. */ - packet.fd = orig_packet->fd; - packet.timestamp = time(NULL); - - debug_nmb_packet(&packet); - - if(loopback_this_packet) - { - struct packet_struct *lo_packet; - DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&packet)) == NULL) - return; - queue_packet(lo_packet); - } - else if (!send_packet(&packet)) - { - DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", - inet_ntoa(packet.ip),packet.port)); - } -} - -/******************************************************************* - Queue a packet into a packet queue -******************************************************************/ -static void queue_packet(struct packet_struct *packet) -{ - struct packet_struct *p; - - if (!packet_queue) - { - packet->prev = NULL; - packet->next = NULL; - packet_queue = packet; - return; - } - - /* find the bottom */ - for (p=packet_queue;p->next;p=p->next) - ; - - p->next = packet; - packet->next = NULL; - packet->prev = p; -} - -/**************************************************************************** - Try and find a matching subnet record for a datagram port 138 packet. -****************************************************************************/ - -static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p) -{ - struct subnet_record *subrec; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If the subnet record is the remote announce broadcast subnet, - hack it here to be the first subnet. This is really gross and - is needed due to people turning on port 137/138 broadcast - forwarding on their routers. May fire and brimstone rain - down upon them... - */ - - return FIRST_SUBNET; -} - -/**************************************************************************** -Dispatch a browse frame from port 138 to the correct processing function. -****************************************************************************/ -static void process_browse_packet(struct packet_struct *p, char *buf,int len) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int command = CVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, lp_netbios_scope())) - { - DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, lp_netbios_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \ -%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_host_announce(subrec, p, buf+1); - break; - } - case ANN_DomainAnnouncement: - { - debug_browse_data(buf, len); - process_workgroup_announce(subrec, p, buf+1); - break; - } - case ANN_LocalMasterAnnouncement: - { - debug_browse_data(buf, len); - process_local_master_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - debug_browse_data(buf, len); - process_announce_request(subrec, p, buf+1); - break; - } - case ANN_Election: - { - debug_browse_data(buf, len); - process_election(subrec, p, buf+1); - break; - } - case ANN_GetBackupListReq: - { - debug_browse_data(buf, len); - process_get_backup_list_request(subrec, p, buf+1); - break; - } - case ANN_GetBackupListResp: - { - debug_browse_data(buf, len); - /* We never send ANN_GetBackupListReq so we - should never get these. */ - DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \ -packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); - break; - } - case ANN_ResetBrowserState: - { - debug_browse_data(buf, len); - process_reset_browser(subrec, p, buf+1); - break; - } - case ANN_MasterAnnouncement: - { - /* Master browser datagrams must be processed - on the unicast subnet. */ - subrec = unicast_subnet; - - debug_browse_data(buf, len); - process_master_browser_announce(subrec, p, buf+1); - break; - } - case ANN_BecomeBackup: - { - /* - * We don't currently implement this. Log it just in case. - */ - debug_browse_data(buf, len); - DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \ -command ANN_BecomeBackup from %s IP %s to %s\n", - subrec->subnet_name, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - break; - } - default: - { - debug_browse_data(buf, len); - DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } -} - -/**************************************************************************** - Dispatch a LanMan browse frame from port 138 to the correct processing function. -****************************************************************************/ -static void process_lanman_packet(struct packet_struct *p, char *buf,int len) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int command = SVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, lp_netbios_scope())) - { - DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, lp_netbios_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \ -%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_lm_host_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - process_lm_announce_request(subrec, p, buf+1); - break; - } - default: - { - DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } -} - -/**************************************************************************** - Determine if a packet is for us on port 138. Note that to have any chance of - being efficient we need to drop as many packets as possible at this - stage as subsequent processing is expensive. -****************************************************************************/ - -static BOOL listening(struct packet_struct *p,struct nmb_name *nbname) -{ - struct subnet_record *subrec = NULL; - - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - break; - } - - if(subrec == NULL) - subrec = unicast_subnet; - - return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL); -} - -/**************************************************************************** - Process udp 138 datagrams -****************************************************************************/ -static void process_dgram(struct packet_struct *p) -{ - char *buf; - char *buf2; - int len; - struct dgram_packet *dgram = &p->packet.dgram; - - /* If we aren't listening to the destination name then ignore the packet */ - if (!listening(p,&dgram->dest_name)) - { - unexpected_packet(p); - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); - return; - } - - if (dgram->header.msg_type != 0x10 && - dgram->header.msg_type != 0x11 && - dgram->header.msg_type != 0x12) - { - unexpected_packet(p); - /* Don't process error packets etc yet */ - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ -an error packet of type %x\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); - return; - } - - buf = &dgram->data[0]; - buf -= 4; /* XXXX for the pseudo tcp length - - someday I need to get rid of this */ - - if (CVAL(buf,smb_com) != SMBtrans) - return; - - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - - if (len <= 0) - return; - - if (buf2 + len > buf + sizeof(dgram->data)) { - DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", - nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),len)); - len = (buf + sizeof(dgram->data)) - buf; - } - - DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", - nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); - - - /* Datagram packet received for the browser mailslot */ - if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) - { - process_browse_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the LAN Manager mailslot */ - if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { - process_lanman_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the domain logon mailslot */ - if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT); - return; - } - - /* Datagram packet received for the NT domain logon mailslot */ - if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT); - return; - } - - unexpected_packet(p); -} - -/**************************************************************************** - Validate a response nmb packet. -****************************************************************************/ - -static BOOL validate_nmb_response_packet( struct nmb_packet *nmb ) -{ - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - if (nmb->header.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1)) - { - DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - case NMB_WACK_OPCODE: - /* Check WACK response here. */ - if (nmb->header.ancount != 1) - { - DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; -} - -/**************************************************************************** - Validate a request nmb packet. -****************************************************************************/ - -static BOOL validate_nmb_packet( struct nmb_packet *nmb ) -{ - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.qdcount == 0) || - ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) && - (nmb->question.question_type != QUESTION_TYPE_NB_STATUS))) - { - DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; -} - -/**************************************************************************** - Find a subnet (and potentially a response record) for a packet. -****************************************************************************/ - -static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p, - struct response_record **pprrec) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct response_record *rrec = NULL; - struct subnet_record *subrec = NULL; - - if(pprrec != NULL) - *pprrec = NULL; - - if(nmb->header.response) - { - /* It's a response packet. Find a record for it or it's an error. */ - - rrec = find_response_record( &subrec, nmb->header.name_trn_id); - if(rrec == NULL) - { - DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n", - nmb->header.name_trn_id)); - unexpected_packet(p); - return NULL; - } - - if(subrec == NULL) - { - DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n", - nmb->header.name_trn_id)); - return NULL; - } - - if(pprrec != NULL) - *pprrec = rrec; - return subrec; - } - - /* Try and see what subnet this packet belongs to. */ - - /* WINS server ? */ - if(packet_is_for_wins_server(p)) - return wins_server_subnet; - - /* If it wasn't a broadcast packet then send to the UNICAST subnet. */ - if(nmb->header.nm_flags.bcast == False) - return unicast_subnet; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If none match it must have been a directed broadcast - assign - the remote_broadcast_subnet. */ - return remote_broadcast_subnet; -} - -/**************************************************************************** - Process a nmb request packet - validate the packet and route it. -****************************************************************************/ - -static void process_nmb_request(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - - debug_nmb_packet(p); - - /* Ensure we have a good packet. */ - if(validate_nmb_packet(nmb)) - return; - - /* Allocate a subnet to this packet - if we cannot - fail. */ - if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL) - return; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_registration_request(subrec, p); - else - process_name_registration_request(subrec, p); - break; - - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: - if(subrec == wins_server_subnet) - wins_process_name_refresh_request(subrec, p); - else - process_name_refresh_request(subrec, p); - break; - - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_multihomed_name_registration_request(subrec, p); - else - { - DEBUG(0,("process_nmb_request: Multihomed registration request must be \ -directed at a WINS server.\n")); - } - break; - - case NMB_NAME_QUERY_OPCODE: - switch (nmb->question.question_type) - { - case QUESTION_TYPE_NB_QUERY: - { - if(subrec == wins_server_subnet) - wins_process_name_query_request(subrec, p); - else - process_name_query_request(subrec, p); - break; - } - case QUESTION_TYPE_NB_STATUS: - { - if(subrec == wins_server_subnet) - { - DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \ -not allowed.\n")); - break; - } - else - process_node_status_request(subrec, p); - break; - } - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_release_request(subrec, p); - else - process_name_release_request(subrec, p); - break; - } -} - -/**************************************************************************** - Process a nmb response packet - validate the packet and route it. - to either the WINS server or a normal response. -****************************************************************************/ - -static void process_nmb_response(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - struct response_record *rrec = NULL; - - debug_nmb_packet(p); - - if(validate_nmb_response_packet(nmb)) - return; - - if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL) - return; - - if(rrec == NULL) - { - DEBUG(0,("process_nmb_response: response packet received but no response record \ -found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id)); - return; - } - - /* Increment the number of responses received for this record. */ - rrec->num_msgs++; - /* Ensure we don't re-send the request. */ - rrec->repeat_count = 0; - - /* Call the response received function for this packet. */ - (*rrec->resp_fn)(subrec, rrec, p); -} - - -/******************************************************************* - Run elements off the packet queue till its empty -******************************************************************/ - -void run_packet_queue(void) -{ - struct packet_struct *p; - - while ((p = packet_queue)) - { - packet_queue = p->next; - if (packet_queue) - packet_queue->prev = NULL; - p->next = p->prev = NULL; - - switch (p->packet_type) - { - case NMB_PACKET: - if(p->packet.nmb.header.response) - process_nmb_response(p); - else - process_nmb_request(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } - free_packet(p); - } -} - -/******************************************************************* - Retransmit or timeout elements from all the outgoing subnet response - record queues. NOTE that this code must also check the WINS server - subnet for response records to timeout as the WINS server code - can send requests to check if a client still owns a name. - (Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>). -******************************************************************/ - -void retransmit_or_expire_response_records(time_t t) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; - subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) - { - struct response_record *rrec, *nextrrec; - - for (rrec = subrec->responselist; rrec; rrec = nextrrec) - { - nextrrec = rrec->next; - - if (rrec->repeat_time <= t) - { - if (rrec->repeat_count > 0) - { - /* Resend while we have a non-zero repeat_count. */ - if(!send_packet(rrec->packet)) - { - DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \ -to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - } - rrec->repeat_time = t + rrec->repeat_interval; - rrec->repeat_count--; - } - else - { - DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \ -on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - - /* - * Check the flag in this record to prevent recursion if we end - * up in this function again via the timeout function call. - */ - - if(!rrec->in_expiration_processing) - { - - /* - * Set the recursion protection flag in this record. - */ - - rrec->in_expiration_processing = True; - - /* Call the timeout function. This will deal with removing the - timed out packet. */ - if(rrec->timeout_fn) - (*rrec->timeout_fn)(subrec, rrec); - else - { - /* We must remove the record ourself if there is - no timeout function. */ - remove_response_record(subrec, rrec); - } - } /* !rrec->in_expitation_processing */ - } /* rrec->repeat_count > 0 */ - } /* rrec->repeat_time <= t */ - } /* end for rrec */ - } /* end for subnet */ -} - -/**************************************************************************** - Create an fd_set containing all the sockets in the subnet structures, - plus the broadcast sockets. -***************************************************************************/ - -static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number) -{ - int *sock_array = NULL; - struct subnet_record *subrec = NULL; - int count = 0; - int num = 0; - fd_set *pset = (fd_set *)malloc(sizeof(fd_set)); - - if(pset == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail !\n")); - return True; - } - - /* Check that we can add all the fd's we need. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - count++; - - if((count*2) + 2 > FD_SETSIZE) - { - DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ -only use %d.\n", (count*2) + 2, FD_SETSIZE)); - return True; - } - - if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); - return True; - } - - FD_ZERO(pset); - - /* Add in the broadcast socket on 137. */ - FD_SET(ClientNMB,pset); - sock_array[num++] = ClientNMB; - - /* Add in the 137 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->nmb_sock,pset); - sock_array[num++] = subrec->nmb_sock; - } - - /* Add in the broadcast socket on 138. */ - FD_SET(ClientDGRAM,pset); - sock_array[num++] = ClientDGRAM; - - /* Add in the 138 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->dgram_sock,pset); - sock_array[num++] = subrec->dgram_sock; - } - - *listen_number = (count*2) + 2; - - SAFE_FREE(*ppset); - SAFE_FREE(*psock_array); - - *ppset = pset; - *psock_array = sock_array; - - return False; -} - -/**************************************************************************** - Listens for NMB or DGRAM packets, and queues them. - return True if the socket is dead -***************************************************************************/ - -BOOL listen_for_packets(BOOL run_election) -{ - static fd_set *listen_set = NULL; - static int listen_number = 0; - static int *sock_array = NULL; - int i; - - fd_set fds; - int selrtn; - struct timeval timeout; -#ifndef SYNC_DNS - int dns_fd; -#endif - - if(listen_set == NULL || rescan_listen_set) - { - if(create_listen_fdset(&listen_set, &sock_array, &listen_number)) - { - DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); - return True; - } - rescan_listen_set = False; - } - - memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); - -#ifndef SYNC_DNS - dns_fd = asyncdns_fd(); - if (dns_fd != -1) { - FD_SET(dns_fd, &fds); - } -#endif - - - /* - * During elections and when expecting a netbios response packet we - * need to send election packets at tighter intervals. - * Ideally it needs to be the interval (in ms) between time now and - * the time we are expecting the next netbios packet. - */ - - timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; - timeout.tv_usec = 0; - - /* Prepare for the select - allow certain signals. */ - - BlockSignals(False, SIGTERM); - - selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout); - - /* We can only take signals when we are in the select - block them again here. */ - - BlockSignals(True, SIGTERM); - - if(selrtn == -1) { - return False; - } - -#ifndef SYNC_DNS - if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) { - run_dns_queue(); - } -#endif - - for(i = 0; i < listen_number; i++) { - if (i < (listen_number/2)) { - /* Processing a 137 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == global_nmb_port && - packet->packet.nmb.header.nm_flags.bcast) { - DEBUG(7,("discarding own bcast packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } else { - /* Processing a 138 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == DGRAM_PORT) { - DEBUG(7,("discarding own dgram packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } /* end processing 138 socket. */ - } /* end for */ - return False; -} - -/**************************************************************************** - Construct and send a netbios DGRAM. -**************************************************************************/ -BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf,int len, - const char *srcname, int src_type, - const char *dstname, int dest_type, - struct in_addr dest_ip,struct in_addr src_ip, - int dest_port) -{ - BOOL loopback_this_packet = False; - struct packet_struct p; - struct dgram_packet *dgram = &p.packet.dgram; - char *ptr,*p2; - char tmp[4]; - - memset((char *)&p,'\0',sizeof(p)); - - if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ - loopback_this_packet = True; - - /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ - - /* DIRECT GROUP or UNIQUE datagram. */ - dgram->header.msg_type = unique ? 0x10 : 0x11; - dgram->header.flags.node_type = M_NODE; - dgram->header.flags.first = True; - dgram->header.flags.more = False; - dgram->header.dgm_id = generate_name_trn_id(); - dgram->header.source_ip = src_ip; - dgram->header.source_port = DGRAM_PORT; - dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ - dgram->header.packet_offset = 0; - - make_nmb_name(&dgram->source_name,srcname,src_type); - make_nmb_name(&dgram->dest_name,dstname,dest_type); - - ptr = &dgram->data[0]; - - /* Setup the smb part. */ - ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ - memcpy(tmp,ptr,4); - set_message(ptr,17,23 + len,True); - memcpy(ptr,tmp,4); - - SCVAL(ptr,smb_com,SMBtrans); - SSVAL(ptr,smb_vwv1,len); - SSVAL(ptr,smb_vwv11,len); - SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); - SSVAL(ptr,smb_vwv13,3); - SSVAL(ptr,smb_vwv14,1); - SSVAL(ptr,smb_vwv15,1); - SSVAL(ptr,smb_vwv16,2); - p2 = smb_buf(ptr); - pstrcpy(p2,mailslot); - p2 = skip_string(p2,1); - - memcpy(p2,buf,len); - p2 += len; - - dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ - - p.ip = dest_ip; - p.port = dest_port; - p.fd = find_subnet_mailslot_fd_for_address( src_ip ); - p.timestamp = time(NULL); - p.packet_type = DGRAM_PACKET; - - DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, - nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); - DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); - - debug_browse_data(buf, len); - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_mailslot: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&p)) == NULL) - return False; - queue_packet(lo_packet); - return True; - } - else - return(send_packet(&p)); -} diff --git a/source4/nmbd/nmbd_processlogon.c b/source4/nmbd/nmbd_processlogon.c deleted file mode 100644 index 1fcfd11a3e..0000000000 --- a/source4/nmbd/nmbd_processlogon.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - Copyright (C) Jim McDonough 2002 - Copyright (C) Anthony Liguori 2002 - - 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. - - Revision History: - -*/ - -#include "includes.h" - -struct sam_database_info { - uint32 index; - uint32 serial_lo, serial_hi; - uint32 date_lo, date_hi; -}; - -/**************************************************************************** -Send a message to smbd to do a sam delta sync -**************************************************************************/ -static void send_repl_message(uint32 low_serial) -{ - TDB_CONTEXT *tdb; - - tdb = tdb_open_log(lock_path("connections.tdb"), 0, - TDB_DEFAULT, O_RDONLY, 0); - - if (!tdb) { - DEBUG(3, ("send_repl_message(): failed to open connections " - "database\n")); - return; - } - - DEBUG(3, ("sending replication message, serial = 0x%04x\n", - low_serial)); - - message_send_all(tdb, MSG_SMB_SAM_REPL, &low_serial, - sizeof(low_serial), False, NULL); - - tdb_close(tdb); -} - -/**************************************************************************** -Process a domain logon packet -**************************************************************************/ - -void process_logon_packet(struct packet_struct *p, char *buf,int len, - const char *mailslot) -{ - struct dgram_packet *dgram = &p->packet.dgram; - pstring my_name; - fstring reply_name; - pstring outbuf; - int code; - uint16 token = 0; - uint32 ntversion = 0; - uint16 lmnttoken = 0; - uint16 lm20token = 0; - uint32 domainsidsize; - BOOL short_request = False; - char *getdc; - char *uniuser; /* Unicode user name. */ - pstring ascuser; - char *unicomp; /* Unicode computer name. */ - - memset(outbuf, 0, sizeof(outbuf)); - - if (!lp_domain_logons()) - { - DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \ -logons are not enabled.\n", inet_ntoa(p->ip) )); - return; - } - - pstrcpy(my_name, lp_netbios_name()); - - code = SVAL(buf,0); - DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); - - switch (code) - { - case 0: - { - char *q = buf + 2; - char *machine = q; - char *user = skip_string(machine,1); - - getdc = skip_string(user,1); - q = skip_string(getdc,1); - token = SVAL(q,3); - - fstrcpy(reply_name,my_name); - - DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - - q = outbuf; - SSVAL(q, 0, 6); - q += 2; - - fstrcpy(reply_name, "\\\\"); - fstrcat(reply_name, my_name); - fstrcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */ - - SSVAL(q, 0, token); - q += 2; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - lp_netbios_name(), 0x0, - machine, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - case QUERYFORPDC: - { - char *q = buf + 2; - char *machine = q; - - if (!lp_domain_master()) - { - /* We're not Primary Domain Controller -- ignore this */ - return; - } - - getdc = skip_string(machine,1); - q = skip_string(getdc,1); - q = ALIGN2(q, buf); - - /* at this point we can work out if this is a W9X or NT style - request. Experiments show that the difference is wether the - packet ends here. For a W9X request we now end with a pair of - bytes (usually 0xFE 0xFF) whereas with NT we have two further - strings - the following is a simple way of detecting this */ - if (len - PTR_DIFF(q, buf) <= 3) { - short_request = True; - } else { - unicomp = q; - - /* A full length (NT style) request */ - q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len != 0) { - q += dom_len + 1; - } - q += 16; - } - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - } - - /* Construct reply. */ - q = outbuf; - SSVAL(q, 0, QUERYFORPDC_R); - q += 2; - - fstrcpy(reply_name,my_name); - fstrcpy(q, reply_name); - q = skip_string(q, 1); /* PDC name */ - - /* PDC and domain name */ - if (!short_request) /* Make a full reply */ - { - q = ALIGN2(q, outbuf); - - q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */ - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/ - SIVAL(q, 0, 1); /* our nt version */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - } - - /* RJS, 21-Feb-2000, we send a short reply if the request was short */ - - DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \ -reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", - machine,inet_ntoa(p->ip), reply_name, lp_workgroup(), - QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken, - (uint32)lm20token )); - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - lp_netbios_name(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - return; - } - - case SAMLOGON: - { - char *q = buf + 2; - fstring asccomp; - - q += 2; - unicomp = q; - uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); - getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); - q = skip_string(getdc,1); - q += 4; /* Account Control Bits - indicating username type */ - domainsidsize = IVAL(q, 0); - q += 4; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len)); - - if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { - q += domainsidsize; - q = ALIGN4(q, buf); - } - - DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) )); - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { - q += dom_len + 1; - } - q += 16; - } - - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - q += 8; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); - - /* - * we respond regadless of whether the machine is in our password - * database. If it isn't then we let smbd send an appropriate error. - * Let's ignore the SID. - */ - pull_ucs2_pstring(ascuser, uniuser); - pull_ucs2_fstring(asccomp, unicomp); - DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); - - fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ - fstrcat(reply_name, my_name); - - DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", - asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), - SAMLOGON_R ,lmnttoken)); - - /* Construct reply. */ - - q = outbuf; - /* we want the simple version unless we are an ADS PDC..which means */ - /* never, at least for now */ - if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { - if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ - } else { - SSVAL(q, 0, SAMLOGON_R); - } - - q += 2; - - q += dos_PutUniCode(q, reply_name,sizeof(pstring), True); - q += dos_PutUniCode(q, ascuser, sizeof(pstring), True); - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); - } -#ifdef HAVE_ADS - else { - GUID domain_guid; - pstring domain; - char *hostname = NULL; - char *component, *dc, *q1; - uint8 size; - - get_mydomname(domain); - hostname = get_myname(); - - if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ - } else { - SSVAL(q, 0, SAMLOGON_AD_R); - } - q += 2; - - SSVAL(q, 0, 0); - q += 2; - SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| - ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); - q += 4; - - /* Push Domain GUID */ - if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { - DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); - return; - } - memcpy(q, &domain_guid, sizeof(domain_guid)); - q += sizeof(domain_guid); - - /* Push domain components */ - dc = domain; - q1 = q; - while ((component = strtok(dc, "."))) { - dc = NULL; - size = push_ascii(&q[1], component, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - } - SCVAL(q, 0, 0); q++; - SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */ - q += 2; /* it must follow the domain name. */ - - /* Push dns host name */ - size = push_ascii(&q[1], hostname, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */ - q += 2; /* it must follow the domain name. */ - - /* Push NETBIOS of domain */ - size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); - SCVAL(q, 0, size); - q += (size + 1); - SCVAL(q, 0, 0); q++; /* is this a null terminator or empty field */ - /* null terminator would not be needed because size is included */ - - /* Push NETBIOS of hostname */ - size = push_ascii(&q[1], my_name, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - SCVAL(q, 0, 0); q++; /* null terminator or empty field? */ - - /* Push user account */ - size = push_ascii(&q[1], ascuser, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - /* Push 'Default-First-Site-Name' */ - size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - SSVAL(q, 0, 0xc000); /* unknown */ - SCVAL(q, 2, PTR_DIFF(q,q1)); - SCVAL(q, 3, 0x10); /* unknown */ - q += 4; - - SIVAL(q, 0, 0x00000002); q += 4; /* unknown */ - SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4; - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - if (hostname) free(hostname); - } -#endif - - /* tell the client what version we are */ - SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); - /* our ntversion */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - lp_netbios_name(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - /* Announce change to UAS or SAM. Send by the domain controller when a - replication event is required. */ - - case SAM_UAS_CHANGE: { - struct sam_database_info *db_info; - char *q = buf + 2; - int i, db_count; - uint32 low_serial; - - /* Header */ - - low_serial = IVAL(q, 0); q += 4; /* Low serial number */ - - q += 4; /* Date/time */ - q += 4; /* Pulse */ - q += 4; /* Random */ - - /* Domain info */ - - q = skip_string(q, 1); /* PDC name */ - q = skip_string(q, 1); /* Domain name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ - - /* Database info */ - - db_count = SVAL(q, 0); q += 2; - - db_info = (struct sam_database_info *) - malloc(sizeof(struct sam_database_info) * db_count); - - if (db_info == NULL) { - DEBUG(3, ("out of memory allocating info for %d databases\n", - db_count)); - return; - } - - for (i = 0; i < db_count; i++) { - db_info[i].index = IVAL(q, 0); - db_info[i].serial_lo = IVAL(q, 4); - db_info[i].serial_hi = IVAL(q, 8); - db_info[i].date_lo = IVAL(q, 12); - db_info[i].date_hi = IVAL(q, 16); - q += 20; - } - - /* Domain SID */ - - q += IVAL(q, 0) + 4; /* 4 byte length plus data */ - - q += 2; /* Alignment? */ - - /* Misc other info */ - - q += 4; /* NT version (0x1) */ - q += 2; /* LMNT token (0xff) */ - q += 2; /* LM20 token (0xff) */ - - SAFE_FREE(db_info); /* Not sure whether we need to do anything - useful with these */ - - /* Send message to smbd */ - - send_repl_message(low_serial); - - break; - } - - default: - { - DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); - return; - } - } -} diff --git a/source4/nmbd/nmbd_responserecordsdb.c b/source4/nmbd/nmbd_responserecordsdb.c deleted file mode 100644 index 7e8c8025ae..0000000000 --- a/source4/nmbd/nmbd_responserecordsdb.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios library routines - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern int ClientNMB; - -int num_response_packets = 0; - -/*************************************************************************** - Add an expected response record into the list - **************************************************************************/ - -static void add_response_record(struct subnet_record *subrec, - struct response_record *rrec) -{ - struct response_record *rrec2; - - num_response_packets++; /* count of total number of packets still around */ - - DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", - rrec->response_id, subrec->subnet_name, num_response_packets)); - - if (!subrec->responselist) - { - subrec->responselist = rrec; - rrec->prev = NULL; - rrec->next = NULL; - return; - } - - for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) - ; - - rrec2->next = rrec; - rrec->next = NULL; - rrec->prev = rrec2; -} - -/*************************************************************************** - Remove an expected response record from the list - **************************************************************************/ - -void remove_response_record(struct subnet_record *subrec, - struct response_record *rrec) -{ - if (rrec->prev) - rrec->prev->next = rrec->next; - if (rrec->next) - rrec->next->prev = rrec->prev; - - if (subrec->responselist == rrec) - subrec->responselist = rrec->next; - - if(rrec->userdata) - { - if(rrec->userdata->free_fn) { - (*rrec->userdata->free_fn)(rrec->userdata); - } else { - ZERO_STRUCTP(rrec->userdata); - SAFE_FREE(rrec->userdata); - } - } - - /* Ensure we can delete. */ - rrec->packet->locked = False; - free_packet(rrec->packet); - - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - - num_response_packets--; /* count of total number of packets still around */ -} - -/**************************************************************************** - Create a response record for an outgoing packet. - **************************************************************************/ - -struct response_record *make_response_record( struct subnet_record *subrec, - struct packet_struct *p, - response_function resp_fn, - timeout_response_function timeout_fn, - success_function success_fn, - fail_function fail_fn, - struct userdata_struct *userdata) -{ - struct response_record *rrec; - struct nmb_packet *nmb = &p->packet.nmb; - - if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) - { - DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n")); - return NULL; - } - - memset((char *)rrec, '\0', sizeof(*rrec)); - - rrec->response_id = nmb->header.name_trn_id; - - rrec->resp_fn = resp_fn; - rrec->timeout_fn = timeout_fn; - rrec->success_fn = success_fn; - rrec->fail_fn = fail_fn; - - rrec->packet = p; - - if(userdata) - { - /* Intelligent userdata. */ - if(userdata->copy_fn) - { - if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) - { - DEBUG(0,("make_response_queue_record: copy fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - } - else - { - /* Primitive userdata, do a memcpy. */ - if((rrec->userdata = (struct userdata_struct *) - malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) - { - DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - rrec->userdata->copy_fn = userdata->copy_fn; - rrec->userdata->free_fn = userdata->free_fn; - rrec->userdata->userdata_len = userdata->userdata_len; - memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len); - } - } - else - rrec->userdata = NULL; - - rrec->num_msgs = 0; - - if(!nmb->header.nm_flags.bcast) - rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */ - else - rrec->repeat_interval = 1; /* XXXX should be in ms */ - rrec->repeat_count = 3; /* 3 retries */ - rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */ - - /* This packet is not being processed. */ - rrec->in_expiration_processing = False; - - /* Lock the packet so we won't lose it while it's on the list. */ - p->locked = True; - - add_response_record(subrec, rrec); - - return rrec; -} - -/**************************************************************************** - Find a response in a subnet's name query response list. - **************************************************************************/ - -static struct response_record *find_response_record_on_subnet( - struct subnet_record *subrec, uint16 id) -{ - struct response_record *rrec = NULL; - - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - if (rrec->response_id == id) - { - DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n", - id, subrec->subnet_name)); - break; - } - } - return rrec; -} - -/**************************************************************************** - Find a response in any subnet's name query response list. - **************************************************************************/ - -struct response_record *find_response_record(struct subnet_record **ppsubrec, - uint16 id) -{ - struct response_record *rrec = NULL; - - for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); - (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) - { - if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL) - return rrec; - } - - /* There should never be response records on the remote_broadcast subnet. - Sanity check to ensure this is so. */ - if(remote_broadcast_subnet->responselist != NULL) - { - DEBUG(0,("find_response_record: response record found on subnet %s. This should \ -never happen !\n", remote_broadcast_subnet->subnet_name)); - } - - /* Now check the WINS server subnet if it exists. */ - if(wins_server_subnet != NULL) - { - *ppsubrec = wins_server_subnet; - if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL) - return rrec; - } - - DEBUG(0,("find_response_record: response packet id %hu received with no \ -matching record.\n", id)); - - *ppsubrec = NULL; - - return NULL; -} - -/**************************************************************************** - Check if a refresh is queued for a particular name on a particular subnet. - **************************************************************************/ - -BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec) -{ - struct response_record *rrec = NULL; - - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - struct packet_struct *p = rrec->packet; - struct nmb_packet *nmb = &p->packet.nmb; - - if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) || - (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) - { - /* Yes it's a queued refresh - check if the name is correct. */ - if(nmb_name_equal(&nmb->question.question_name, &namerec->name)) - return True; - } - } - - return False; -} diff --git a/source4/nmbd/nmbd_sendannounce.c b/source4/nmbd/nmbd_sendannounce.c deleted file mode 100644 index 191a3b7c7b..0000000000 --- a/source4/nmbd/nmbd_sendannounce.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - SMB Version handling - Copyright (C) John H Terpstra 1995-1998 - - 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" - -extern int updatecount; -extern BOOL found_lm_clients; - -/**************************************************************************** - Send a browser reset packet. -**************************************************************************/ - -void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip) -{ - pstring outbuf; - char *p; - - DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n", - reset_type, to_name, to_type, inet_ntoa(to_ip) )); - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_ResetBrowserState); - p++; - SCVAL(p,0,reset_type); - p++; - - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - lp_netbios_name(), 0x0, to_name, to_type, to_ip, - FIRST_SUBNET->myip, DGRAM_PORT); -} - -/**************************************************************************** - Broadcast a packet to the local net requesting that all servers in this - workgroup announce themselves to us. - **************************************************************************/ - -void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work) -{ - pstring outbuf; - char *p; - - work->needannounce = True; - - DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ -to subnet %s\n", work->work_group, subrec->subnet_name)); - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_AnnouncementRequest); - p++; - - SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */ - p++; - p += push_string(NULL, p+1, lp_netbios_name(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - - send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - lp_netbios_name(), 0x0, work->work_group,0x1e, subrec->bcast_ip, - subrec->myip, DGRAM_PORT); -} - -/**************************************************************************** - Broadcast an announcement. - **************************************************************************/ - -static void send_announcement(struct subnet_record *subrec, int announce_type, - const char *from_name, const char *to_name, int to_type, struct in_addr to_ip, - time_t announce_interval, - const char *server_name, int server_type, const char *server_comment) -{ - pstring outbuf; - char *p; - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf+1; - - SCVAL(outbuf,0,announce_type); - - /* Announcement parameters. */ - SCVAL(p,0,updatecount); - SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */ - - push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - - SCVAL(p,21,lp_major_announce_version()); /* Major version. */ - SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */ - - SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */ - SSVAL(p,27,BROWSER_ELECTION_VERSION); - SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */ - - p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE); - - send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, - DGRAM_PORT); -} - -/**************************************************************************** - Broadcast a LanMan announcement. -**************************************************************************/ - -static void send_lm_announcement(struct subnet_record *subrec, int announce_type, - char *from_name, char *to_name, int to_type, struct in_addr to_ip, - time_t announce_interval, - char *server_name, int server_type, char *server_comment) -{ - pstring outbuf; - char *p=outbuf; - - memset(outbuf,'\0',sizeof(outbuf)); - - SSVAL(p,0,announce_type); - SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - SCVAL(p,6,lp_major_announce_version()); /* Major version. */ - SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */ - SSVAL(p,8,announce_interval); /* In seconds - according to spec. */ - - p += 10; - /*StrnCpy(p,server_name,15); - strupper(p); - p = skip_string(p,1); - pstrcpy(p,server_comment); - p = skip_string(p,1);*/ - p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE); - - send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, - DGRAM_PORT); -} - -/**************************************************************************** - We are a local master browser. Announce this to WORKGROUP<1e>. -****************************************************************************/ - -static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work, - struct server_record *servrec) -{ - /* Ensure we don't have the prohibited bit set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", - type, lp_netbios_name(), subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_LocalMasterAnnouncement, - lp_netbios_name(), /* From nbt name. */ - work->work_group, 0x1e, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - lp_netbios_name(), /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); -} - -/**************************************************************************** - Announce the workgroup WORKGROUP to MSBROWSE<01>. -****************************************************************************/ - -static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work) -{ - DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n", - subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_DomainAnnouncement, - lp_netbios_name(), /* From nbt name. */ - MSBROWSE, 0x1, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - work->work_group, /* Name to announce. */ - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */ - lp_netbios_name()); /* From name as comment. */ -} - -/**************************************************************************** - Announce the given host to WORKGROUP<1d>. -****************************************************************************/ - -static void send_host_announcement(struct subnet_record *subrec, struct work_record *work, - struct server_record *servrec) -{ - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x1d, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); -} - -/**************************************************************************** - Announce the given LanMan host -****************************************************************************/ - -static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work, - struct server_record *servrec, int lm_interval) -{ - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval)); - - send_lm_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x00, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - lm_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); -} - -/**************************************************************************** - Announce a server record. - ****************************************************************************/ - -static void announce_server(struct subnet_record *subrec, struct work_record *work, - struct server_record *servrec) -{ - /* Only do domain announcements if we are a master and it's - our primary name we're being asked to announce. */ - - if (AM_LOCAL_MASTER_BROWSER(work) && strequal(lp_netbios_name(),servrec->serv.name)) - { - send_local_master_announcement(subrec, work, servrec); - send_workgroup_announcement(subrec, work); - } - else - { - send_host_announcement(subrec, work, servrec); - } -} - -/**************************************************************************** - Go through all my registered names on all broadcast subnets and announce - them if the timeout requires it. - **************************************************************************/ - -void announce_my_server_names(time_t t) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (work->needannounce) - { - /* Drop back to a max 3 minute announce. This is to prevent a - single lost packet from breaking things for too long. */ - - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - work->needannounce = False; - } - - /* Announce every minute at first then progress to every 12 mins */ - if ((t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60)) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - announce_server(subrec, work, servrec); - } - } /* if work */ - } /* for subrec */ -} - -/**************************************************************************** - Go through all my registered names on all broadcast subnets and announce - them as a LanMan server if the timeout requires it. -**************************************************************************/ - -void announce_my_lm_server_names(time_t t) -{ - struct subnet_record *subrec; - static time_t last_lm_announce_time=0; - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - return; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - return; - } - - /* Otherwise: must have been set to 1 (Yes), or LM clients *have* - been detected. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval )) - continue; - - last_lm_announce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - /* skipping equivalent of announce_server() */ - send_lm_host_announcement(subrec, work, servrec, announce_interval); - } - } /* if work */ - } /* for subrec */ -} - -/* Announce timer. Moved into global static so it can be reset - when a machine becomes a local master browser. */ -static time_t announce_timer_last=0; - -/**************************************************************************** - Reset the announce_timer so that a local master browser announce will be done - immediately. - ****************************************************************************/ - -void reset_announce_timer(void) -{ - announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); -} - -/**************************************************************************** - Announce myself as a local master browser to a domain master browser. - **************************************************************************/ - -void announce_myself_to_domain_master_browser(time_t t) -{ - struct subnet_record *subrec; - struct work_record *work; - - if(!we_are_a_wins_client()) - { - DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n")); - return; - } - - if (!announce_timer_last) - announce_timer_last = t; - - if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) - { - DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n", - (int)t, (int)announce_timer_last, - CHECK_TIME_MST_ANNOUNCE * 60 )); - return; - } - - announce_timer_last = t; - - /* Look over all our broadcast subnets to see if any of them - has the state set as local master browser. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - for (work = subrec->workgrouplist; work; work = work->next) - { - if (AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \ -workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - - /* Look in nmbd_browsersync.c for the rest of this code. */ - announce_and_sync_with_domain_master_browser(subrec, work); - } - } - } -} - -/**************************************************************************** -Announce all samba's server entries as 'gone'. -This must *only* be called on shutdown. -****************************************************************************/ - -void announce_my_servers_removed(void) -{ - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - struct server_record *servrec; - - work->announce_interval = 0; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (!is_myname(servrec->serv.name)) - continue; - servrec->serv.type = 0; - if(AM_LOCAL_MASTER_BROWSER(work)) - send_local_master_announcement(subrec, work, servrec); - send_host_announcement(subrec, work, servrec); - - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - continue; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - continue; - } - - /* - * lm announce was set or we have seen lm announcements, so do - * a lm announcement of host removed. - */ - - send_lm_host_announcement(subrec, work, servrec, 0); - } - } - } -} - -/**************************************************************************** - Do all the "remote" announcements. These are used to put ourselves - on a remote browse list. They are done blind, no checking is done to - see if there is actually a local master browser at the other end. - **************************************************************************/ - -void announce_remote(time_t t) -{ - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - char *comment; - int stype = lp_default_server_announce(); - - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; - - last_time = t; - - s = lp_remote_announce(); - if (!*s) - return; - - comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); - - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d/WORKGROUP with - WORKGROUP being optional */ - const char *wgroup; - char *pwgroup; - int i; - - pwgroup = strchr_m(s2,'/'); - if (pwgroup) - *pwgroup++ = 0; - if (!pwgroup || !*pwgroup) - wgroup = lp_workgroup(); - else - wgroup = pwgroup; - - addr = *interpret_addr2(s2); - - /* Announce all our names including aliases */ - /* Give the ip address as the address of our first - broadcast subnet. */ - - for(i=0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - - DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", - name, inet_ntoa(addr) )); - - send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, - name, /* From nbt name. */ - wgroup, 0x1d, /* To nbt name. */ - addr, /* To ip. */ - REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ - name, /* Name to announce. */ - stype, /* Type field. */ - comment); - } - } -} - -/**************************************************************************** - Implement the 'remote browse sync' feature Andrew added. - These are used to put our browse lists into remote browse lists. - **************************************************************************/ - -void browse_sync_remote(time_t t) -{ - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - struct work_record *work; - pstring outbuf; - char *p; - - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; - - last_time = t; - - s = lp_remote_browse_sync(); - if (!*s) - return; - - /* - * We only do this if we are the local master browser - * for our workgroup on the firsst subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n", - lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } - - if(!AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \ -for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_MasterAnnouncement); - p++; - - StrnCpy(p,lp_netbios_name(),15); - strupper(p); - p = skip_string(p,1); - - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d */ - addr = *interpret_addr2(s2); - - DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n", - lp_netbios_name(), inet_ntoa(addr) )); - - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - lp_netbios_name(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT); - } -} diff --git a/source4/nmbd/nmbd_serverlistdb.c b/source4/nmbd/nmbd_serverlistdb.c deleted file mode 100644 index ee0c021d5d..0000000000 --- a/source4/nmbd/nmbd_serverlistdb.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern int ClientNMB; - -int updatecount = 0; - -/******************************************************************* - Remove all the servers in a work group. - ******************************************************************/ - -void remove_all_servers(struct work_record *work) -{ - struct server_record *servrec; - struct server_record *nexts; - - for (servrec = work->serverlist; servrec; servrec = nexts) - { - DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name)); - nexts = servrec->next; - - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; - - if (work->serverlist == servrec) - work->serverlist = servrec->next; - - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); - - } - - work->subnet->work_changed = True; -} - -/*************************************************************************** - Add a server into the a workgroup serverlist. - **************************************************************************/ - -static void add_server_to_workgroup(struct work_record *work, - struct server_record *servrec) -{ - struct server_record *servrec2; - - if (!work->serverlist) - { - work->serverlist = servrec; - servrec->prev = NULL; - servrec->next = NULL; - return; - } - - for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next) - ; - - servrec2->next = servrec; - servrec->next = NULL; - servrec->prev = servrec2; - work->subnet->work_changed = True; -} - -/**************************************************************************** - Find a server in a server list. - **************************************************************************/ - -struct server_record *find_server_in_workgroup(struct work_record *work, const char *name) -{ - struct server_record *ret; - - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - return ret; - } - return NULL; -} - - -/**************************************************************************** - Remove a server entry from this workgroup. - ****************************************************************************/ - -void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec) -{ - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; - - if (work->serverlist == servrec) - work->serverlist = servrec->next; - - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); - work->subnet->work_changed = True; -} - -/**************************************************************************** - Create a server entry on this workgroup. - ****************************************************************************/ - -struct server_record *create_server_on_workgroup(struct work_record *work, - const char *name,int servertype, - int ttl, const char *comment) -{ - struct server_record *servrec; - - if (name[0] == '*') - { - DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n", - name)); - return (NULL); - } - - if((servrec = find_server_in_workgroup(work, name)) != NULL) - { - DEBUG(0,("create_server_on_workgroup: Server %s already exists on \ -workgroup %s. This is a bug.\n", name, work->work_group)); - return NULL; - } - - if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) - { - DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n")); - return NULL; - } - - memset((char *)servrec,'\0',sizeof(*servrec)); - - servrec->subnet = work->subnet; - - StrnCpy(servrec->serv.name,name,sizeof(servrec->serv.name)-1); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); - strupper(servrec->serv.name); - servrec->serv.type = servertype; - - update_server_ttl(servrec, ttl); - - add_server_to_workgroup(work, servrec); - - DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \ -workgroup %s.\n", name,servertype,comment, work->work_group)); - - work->subnet->work_changed = True; - - return(servrec); -} - -/******************************************************************* - Update the ttl field of a server record. -*******************************************************************/ - -void update_server_ttl(struct server_record *servrec, int ttl) -{ - if(ttl > lp_max_ttl()) - ttl = lp_max_ttl(); - - if(is_myname(servrec->serv.name)) - servrec->death_time = PERMANENT_TTL; - else - servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - - servrec->subnet->work_changed = True; -} - -/******************************************************************* - Expire old servers in the serverlist. A time of -1 indicates - everybody dies except those with a death_time of PERMANENT_TTL (which is 0). - This should only be called from expire_workgroups_and_servers(). - ******************************************************************/ - -void expire_servers(struct work_record *work, time_t t) -{ - struct server_record *servrec; - struct server_record *nexts; - - for (servrec = work->serverlist; servrec; servrec = nexts) - { - nexts = servrec->next; - - if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) - { - DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name)); - remove_server_from_workgroup(work, servrec); - work->subnet->work_changed = True; - } - } -} - -/******************************************************************* - Decide if we should write out a server record for this server. - We return zero if we should not. Check if we've already written - out this server record from an earlier subnet. -******************************************************************/ - -static uint32 write_this_server_name( struct subnet_record *subrec, - struct work_record *work, - struct server_record *servrec) -{ - struct subnet_record *ssub; - struct work_record *iwork; - - /* Go through all the subnets we have already seen. */ - for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) - { - for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) - { - if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) - { - /* - * We have already written out this server record, don't - * do it again. This gives precedence to servers we have seen - * on the broadcast subnets over servers that may have been - * added via a sync on the unicast_subet. - * - * The correct way to do this is to have a serverlist file - * per subnet - this means changes to smbd as well. I may - * add this at a later date (JRA). - */ - - return 0; - } - } - } - - return servrec->serv.type; -} - -/******************************************************************* - Decide if we should write out a workgroup record for this workgroup. - We return zero if we should not. Don't write out lp_workgroup() (we've - already done it) and also don't write out a second workgroup record - on the unicast subnet that we've already written out on one of the - broadcast subnets. -******************************************************************/ - -static uint32 write_this_workgroup_name( struct subnet_record *subrec, - struct work_record *work) -{ - struct subnet_record *ssub; - - if(strequal(lp_workgroup(), work->work_group)) - return 0; - - /* This is a workgroup we have seen on a broadcast subnet. All - these have the same type. */ - - if(subrec != unicast_subnet) - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY); - - for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) - { - /* This is the unicast subnet so check if we've already written out - this subnet when we passed over the broadcast subnets. */ - - if(find_workgroup_on_subnet( ssub, work->work_group) != NULL) - return 0; - } - - /* All workgroups on the unicast subnet (except our own, which we - have already written out) cannot be local. */ - - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT); -} - -/******************************************************************* - Write out the browse.dat file. - ******************************************************************/ - -void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type, - const char *local_master_browser_name, const char *description) -{ - fstring tmp; - - slprintf(tmp,sizeof(tmp)-1, "\"%s\"", name); - x_fprintf(fp, "%-25s ", tmp); - x_fprintf(fp, "%08x ", rec_type); - slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", local_master_browser_name); - x_fprintf(fp, "%-30s", tmp); - x_fprintf(fp, "\"%s\"\n", description); -} - -void write_browse_list(time_t t, BOOL force_write) -{ - struct subnet_record *subrec; - struct work_record *work; - struct server_record *servrec; - pstring fname,fnamenew; - uint32 stype; - int i; - XFILE *fp; - BOOL list_changed = force_write; - static time_t lasttime = 0; - - /* Always dump if we're being told to by a signal. */ - if(force_write == False) - { - if (!lasttime) - lasttime = t; - if (t - lasttime < 5) - return; - } - - lasttime = t; - - dump_workgroups(force_write); - - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if(subrec->work_changed) - { - list_changed = True; - break; - } - } - - if(!list_changed) - return; - - updatecount++; - - pstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - pstrcat(fname,"/"); - pstrcat(fname,SERVER_LIST); - pstrcpy(fnamenew,fname); - pstrcat(fnamenew,"."); - - fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644); - - if (!fp) - { - DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n", - fnamenew,strerror(errno))); - return; - } - - /* - * Write out a record for our workgroup. Use the record from the first - * subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n", - lp_workgroup())); - x_fclose(fp); - return; - } - - write_browse_list_entry(fp, work->work_group, - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY, - work->local_master_browser_name, work->work_group); - - /* - * We need to do something special for our own names. - * This is due to the fact that we may be a local master browser on - * one of our broadcast subnets, and a domain master on the unicast - * subnet. We iterate over the subnets and only write out the name - * once. - */ - - for (i=0; my_netbios_names(i); i++) - { - stype = 0; - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL) - continue; - if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL) - continue; - - stype |= servrec->serv.type; - } - - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, my_netbios_names(i), stype, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup()); - } - - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - subrec->work_changed = False; - - for (work = subrec->workgrouplist; work ; work = work->next) - { - /* Write out a workgroup record for a workgroup. */ - uint32 wg_type = write_this_workgroup_name( subrec, work); - - if(wg_type) - { - write_browse_list_entry(fp, work->work_group, wg_type, - work->local_master_browser_name, - work->work_group); - } - - /* Now write out any server records a workgroup may have. */ - - for (servrec = work->serverlist; servrec ; servrec = servrec->next) - { - uint32 serv_type; - - /* We have already written our names here. */ - if(is_myname(servrec->serv.name)) - continue; - - serv_type = write_this_server_name(subrec, work, servrec); - - if(serv_type) - { - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, servrec->serv.name, serv_type, - servrec->serv.comment, work->work_group); - } - } - } - } - - x_fclose(fp); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname)); -} diff --git a/source4/nmbd/nmbd_subnetdb.c b/source4/nmbd/nmbd_subnetdb.c deleted file mode 100644 index 6296826425..0000000000 --- a/source4/nmbd/nmbd_subnetdb.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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. - - Revision History: - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; -extern int global_nmb_port; - -/* This is the broadcast subnets database. */ -struct subnet_record *subnetlist = NULL; - -/* Extra subnets - keep these separate so enumeration code doesn't - run onto it by mistake. */ - -struct subnet_record *unicast_subnet = NULL; -struct subnet_record *remote_broadcast_subnet = NULL; -struct subnet_record *wins_server_subnet = NULL; - -extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ - -/**************************************************************************** - Add a subnet into the list. - **************************************************************************/ - -static void add_subnet(struct subnet_record *subrec) -{ - DLIST_ADD(subnetlist, subrec); -} - -/* ************************************************************************** ** - * Comparison routine for ordering the splay-tree based namelists assoicated - * with each subnet record. - * - * Input: Item - Pointer to the comparison key. - * Node - Pointer to a node the splay tree. - * - * Output: The return value will be <0 , ==0, or >0 depending upon the - * ordinal relationship of the two keys. - * - * ************************************************************************** ** - */ -static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node ) - { - struct name_record *NR = (struct name_record *)Node; - - if( DEBUGLVL( 10 ) ) - { - struct nmb_name *Iname = (struct nmb_name *)Item; - - Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); - Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", - memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), - nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); - } - - return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); - } /* namelist_entry_compare */ - - -/**************************************************************************** -stop listening on a subnet -we don't free the record as we don't have proper reference counting for it -yet and it may be in use by a response record - ****************************************************************************/ -void close_subnet(struct subnet_record *subrec) -{ - DLIST_REMOVE(subnetlist, subrec); - - if (subrec->dgram_sock != -1) { - close(subrec->dgram_sock); - subrec->dgram_sock = -1; - } - if (subrec->nmb_sock != -1) { - close(subrec->nmb_sock); - subrec->nmb_sock = -1; - } -} - - - -/**************************************************************************** - Create a subnet entry. - ****************************************************************************/ - -static struct subnet_record *make_subnet(const char *name, enum subnet_type type, - struct in_addr myip, struct in_addr bcast_ip, - struct in_addr mask_ip) -{ - struct subnet_record *subrec = NULL; - int nmb_sock, dgram_sock; - - /* Check if we are creating a non broadcast subnet - if so don't create - sockets. - */ - - if(type != NORMAL_SUBNET) - { - nmb_sock = -1; - dgram_sock = -1; - } - else - { - /* - * Attempt to open the sockets on port 137/138 for this interface - * and bind them. - * Fail the subnet creation if this fails. - */ - - if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", global_nmb_port ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", DGRAM_PORT ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - /* Make sure we can broadcast from these sockets. */ - set_socket_options(nmb_sock,"SO_BROADCAST"); - set_socket_options(dgram_sock,"SO_BROADCAST"); - - } - - subrec = (struct subnet_record *)malloc(sizeof(*subrec)); - - if (!subrec) - { - DEBUG(0,("make_subnet: malloc fail !\n")); - close(nmb_sock); - close(dgram_sock); - return(NULL); - } - - memset( (char *)subrec, '\0', sizeof(*subrec) ); - (void)ubi_trInitTree( subrec->namelist, - namelist_entry_compare, - ubi_trOVERWRITE ); - - if((subrec->subnet_name = strdup(name)) == NULL) - { - DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); - close(nmb_sock); - close(dgram_sock); - ZERO_STRUCTP(subrec); - SAFE_FREE(subrec); - return(NULL); - } - - DEBUG(2, ("making subnet name:%s ", name )); - DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); - DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); - - subrec->namelist_changed = False; - subrec->work_changed = False; - - subrec->bcast_ip = bcast_ip; - subrec->mask_ip = mask_ip; - subrec->myip = myip; - subrec->type = type; - subrec->nmb_sock = nmb_sock; - subrec->dgram_sock = dgram_sock; - - return subrec; -} - - -/**************************************************************************** - Create a normal subnet -**************************************************************************/ -struct subnet_record *make_normal_subnet(struct interface *iface) -{ - struct subnet_record *subrec; - - subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET, - iface->ip, iface->bcast, iface->nmask); - if (subrec) { - add_subnet(subrec); - } - return subrec; -} - - -/**************************************************************************** - Create subnet entries. -**************************************************************************/ - -BOOL create_subnets(void) -{ - int num_interfaces = iface_count(); - int i; - struct in_addr unicast_ip, ipzero; - extern struct in_addr loopback_ip; - - if(num_interfaces == 0) { - DEBUG(0,("create_subnets: No local interfaces !\n")); - DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); - while (iface_count() == 0) { - sleep(5); - load_interfaces(); - } - } - - num_interfaces = iface_count(); - - /* - * Create subnets from all the local interfaces and thread them onto - * the linked list. - */ - - for (i = 0 ; i < num_interfaces; i++) - { - struct interface *iface = get_interface(i); - - /* - * We don't want to add a loopback interface, in case - * someone has added 127.0.0.1 for smbd, nmbd needs to - * ignore it here. JRA. - */ - - if (ip_equal(iface->ip, loopback_ip)) { - DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); - continue; - } - - if (!make_normal_subnet(iface)) return False; - } - - if (lp_we_are_a_wins_server()) { - /* Pick the first interface ip address as the WINS server ip. */ - unicast_ip = *iface_n_ip(0); - } else { - /* note that we do not set the wins server IP here. We just - set it at zero and let the wins registration code cope - with getting the IPs right for each packet */ - zero_ip(&unicast_ip); - } - - /* - * Create the unicast and remote broadcast subnets. - * Don't put these onto the linked list. - * The ip address of the unicast subnet is set to be - * the WINS server address, if it exists, or ipzero if not. - */ - - unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, - unicast_ip, unicast_ip, unicast_ip); - - zero_ip(&ipzero); - - remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", - REMOTE_BROADCAST_SUBNET, - ipzero, ipzero, ipzero); - - if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) - return False; - - /* - * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on - * the linked list. - */ - - if (lp_we_are_a_wins_server()) - { - if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET", - WINS_SERVER_SUBNET, - ipzero, ipzero, ipzero )) == NULL ) - return False; - } - - return True; -} - -/******************************************************************* -Function to tell us if we can use the unicast subnet. -******************************************************************/ -BOOL we_are_a_wins_client(void) -{ - if (wins_srv_count() > 0) { - return True; - } - - return False; -} - -/******************************************************************* -Access function used by NEXT_SUBNET_INCLUDING_UNICAST -******************************************************************/ - -struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec) -{ - if(subrec == unicast_subnet) - return NULL; - else if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; -} - -/******************************************************************* - Access function used by retransmit_or_expire_response_records() in - nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru> - Needed when we need to enumerate all the broadcast, unicast and - WINS subnets. -******************************************************************/ - -struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec) -{ - if(subrec == unicast_subnet) - { - if(wins_server_subnet) - return wins_server_subnet; - else - return NULL; - } - - if(wins_server_subnet && subrec == wins_server_subnet) - return NULL; - - if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; -} diff --git a/source4/nmbd/nmbd_synclists.c b/source4/nmbd/nmbd_synclists.c deleted file mode 100644 index b9952fb446..0000000000 --- a/source4/nmbd/nmbd_synclists.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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. - -*/ - -/* this file handles asynchronous browse synchronisation requests. The - requests are done by forking and putting the result in a file in the - locks directory. We do it this way because we don't want nmbd to be - blocked waiting for some server to respond on a TCP connection. This - also allows us to have more than 1 sync going at once (tridge) */ - -#include "includes.h" - -struct sync_record { - struct sync_record *next, *prev; - fstring workgroup; - fstring server; - pstring fname; - struct in_addr ip; - pid_t pid; -}; - -/* a linked list of current sync connections */ -static struct sync_record *syncs; - -static XFILE *fp; - -/******************************************************************* - This is the NetServerEnum callback. - Note sname and comment are in UNIX codepage format. - ******************************************************************/ -static void callback(const char *sname, uint32 stype, - const char *comment, void *state) -{ - x_fprintf(fp,"\"%s\" %08X \"%s\"\n", sname, stype, comment); -} - -/******************************************************************* - Synchronise browse lists with another browse server. - Log in on the remote server's SMB port to their IPC$ service, - do a NetServerEnum and record the results in fname -******************************************************************/ -static void sync_child(char *name, int nm_type, - char *workgroup, - struct in_addr ip, BOOL local, BOOL servers, - char *fname) -{ - extern fstring local_machine; - fstring unix_workgroup; - static struct cli_state cli; - uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; - struct nmb_name called, calling; - - /* W2K DMB's return empty browse lists on port 445. Use 139. - * Patch from Andy Levine andyl@epicrealm.com. - */ - - if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) { - return; - } - - make_nmb_name(&calling, local_machine, 0x0); - make_nmb_name(&called , name , nm_type); - - if (!cli_session_request(&cli, &calling, &called)) - { - cli_shutdown(&cli); - return; - } - - if (!cli_negprot(&cli)) { - cli_shutdown(&cli); - return; - } - - if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) { - cli_shutdown(&cli); - return; - } - - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - cli_shutdown(&cli); - return; - } - - /* All the cli_XX functions take UNIX character set. */ - fstrcpy(unix_workgroup, cli.server_domain?cli.server_domain:workgroup); - - /* Fetch a workgroup list. */ - cli_NetServerEnum(&cli, unix_workgroup, - local_type|SV_TYPE_DOMAIN_ENUM, - callback, NULL); - - /* Now fetch a server list. */ - if (servers) { - fstrcpy(unix_workgroup, workgroup); - cli_NetServerEnum(&cli, unix_workgroup, - local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL, - callback, NULL); - } - - cli_shutdown(&cli); -} - - -/******************************************************************* - initialise a browse sync with another browse server. Log in on the - remote server's SMB port to their IPC$ service, do a NetServerEnum - and record the results -******************************************************************/ -void sync_browse_lists(struct work_record *work, - char *name, int nm_type, - struct in_addr ip, BOOL local, BOOL servers) -{ - struct sync_record *s; - static int counter; - - START_PROFILE(sync_browse_lists); - /* Check we're not trying to sync with ourselves. This can - happen if we are a domain *and* a local master browser. */ - if (ismyip(ip)) { -done: - END_PROFILE(sync_browse_lists); - return; - } - - s = (struct sync_record *)malloc(sizeof(*s)); - if (!s) goto done; - - ZERO_STRUCTP(s); - - fstrcpy(s->workgroup, work->work_group); - fstrcpy(s->server, name); - s->ip = ip; - - slprintf(s->fname, sizeof(pstring)-1, - "%s/sync.%d", lp_lockdir(), counter++); - all_string_sub(s->fname,"//", "/", 0); - - DLIST_ADD(syncs, s); - - /* the parent forks and returns, leaving the child to do the - actual sync and call END_PROFILE*/ - CatchChild(); - if ((s->pid = sys_fork())) return; - - BlockSignals( False, SIGTERM ); - - DEBUG(2,("Initiating browse sync for %s to %s(%s)\n", - work->work_group, name, inet_ntoa(ip))); - - fp = x_fopen(s->fname,O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (!fp) { - END_PROFILE(sync_browse_lists); - _exit(1); - } - - sync_child(name, nm_type, work->work_group, ip, local, servers, - s->fname); - - x_fclose(fp); - END_PROFILE(sync_browse_lists); - _exit(0); -} - -/********************************************************************** -handle one line from a completed sync file - **********************************************************************/ -static void complete_one(struct sync_record *s, - char *sname, uint32 stype, char *comment) -{ - struct work_record *work; - struct server_record *servrec; - - stype &= ~SV_TYPE_LOCAL_LIST_ONLY; - - if (stype & SV_TYPE_DOMAIN_ENUM) { - /* See if we can find the workgroup on this subnet. */ - if((work=find_workgroup_on_subnet(unicast_subnet, sname))) { - /* We already know about this workgroup - - update the ttl. */ - update_workgroup_ttl(work,lp_max_ttl()); - } else { - /* Create the workgroup on the subnet. */ - work = create_workgroup_on_subnet(unicast_subnet, - sname, lp_max_ttl()); - if (work) { - /* remember who the master is */ - fstrcpy(work->local_master_browser_name, - comment); - } - } - return; - } - - work = find_workgroup_on_subnet(unicast_subnet, s->workgroup); - if (!work) { - DEBUG(3,("workgroup %s doesn't exist on unicast subnet?\n", - s->workgroup)); - return; - } - - if ((servrec = find_server_in_workgroup( work, sname))) { - /* Check that this is not a locally known - server - if so ignore the entry. */ - if(!(servrec->serv.type & SV_TYPE_LOCAL_LIST_ONLY)) { - /* We already know about this server - update - the ttl. */ - update_server_ttl(servrec, lp_max_ttl()); - /* Update the type. */ - servrec->serv.type = stype; - } - return; - } - - /* Create the server in the workgroup. */ - create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment); -} - - -/********************************************************************** -read the completed sync info - **********************************************************************/ -static void complete_sync(struct sync_record *s) -{ - XFILE *f; - fstring server, type_str; - unsigned type; - pstring comment; - pstring line; - const char *ptr; - int count=0; - - f = x_fopen(s->fname,O_RDONLY, 0); - - if (!f) return; - - while (!x_feof(f)) { - - if (!fgets_slash(line,sizeof(pstring),f)) continue; - - ptr = line; - - if (!next_token(&ptr,server,NULL,sizeof(server)) || - !next_token(&ptr,type_str,NULL, sizeof(type_str)) || - !next_token(&ptr,comment,NULL, sizeof(comment))) { - continue; - } - - sscanf(type_str, "%X", &type); - - complete_one(s, server, type, comment); - - count++; - } - - x_fclose(f); - - unlink(s->fname); - - DEBUG(2,("sync with %s(%s) for workgroup %s completed (%d records)\n", - s->server, inet_ntoa(s->ip), s->workgroup, count)); -} - -/********************************************************************** -check for completion of any of the child processes - **********************************************************************/ -void sync_check_completion(void) -{ - struct sync_record *s, *next; - - for (s=syncs;s;s=next) { - next = s->next; - if (!process_exists(s->pid)) { - /* it has completed - grab the info */ - complete_sync(s); - DLIST_REMOVE(syncs, s); - ZERO_STRUCTP(s); - SAFE_FREE(s); - } - } -} diff --git a/source4/nmbd/nmbd_winsproxy.c b/source4/nmbd/nmbd_winsproxy.c deleted file mode 100644 index 2e65ebb612..0000000000 --- a/source4/nmbd/nmbd_winsproxy.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -/**************************************************************************** -Function called when the name lookup succeeded. -****************************************************************************/ - -static void wins_proxy_name_query_request_success( struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec) -{ - struct packet_struct *original_packet; - struct subnet_record *orig_broadcast_subnet; - struct name_record *namerec; - uint16 nb_flags; - int num_ips; - int i; - int ttl = 3600; /* By default one hour in the cache. */ - struct in_addr *iplist; - - /* Extract the original packet and the original broadcast subnet from - the userdata. */ - - memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) ); - memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); - - nb_flags = get_nb_flags( rrec->rdata ); - - num_ips = rrec->rdlength / 6; - if(num_ips == 0) - { - DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \ -returned for name %s.\n", nmb_namestr(nmbname) )); - return; - } - - if(num_ips == 1) - iplist = &ip; - else - { - if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) - { - DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n")); - return; - } - - for(i = 0; i < num_ips; i++) - putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); - } - - /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ - - if(rrec == PERMANENT_TTL) - ttl = lp_max_ttl(); - - namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name, - nmbname->name_type, nb_flags, ttl, - WINS_PROXY_NAME, num_ips, iplist ); - - if(iplist != &ip) - SAFE_FREE(iplist); - - /* - * Check that none of the IP addresses we are returning is on the - * same broadcast subnet as the original requesting packet. If it - * is then don't reply (although we still need to add the name - * to the cache) as the actual machine will be replying also - * and we don't want two replies to a broadcast query. - */ - - if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) - { - for( i = 0; i < namerec->data.num_ips; i++) - { - if( same_net( namerec->data.ip[i], - orig_broadcast_subnet->myip, - orig_broadcast_subnet->mask_ip ) ) - { - DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ -proxy name and is also on the same subnet (%s) as the requestor. \ -Not replying.\n", - nmb_namestr(&namerec->name), - orig_broadcast_subnet->subnet_name ) ); - return; - } - } - } - - /* Finally reply to the original name query. */ - reply_netbios_packet(original_packet, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rrec->rdata, /* data to send. */ - rrec->rdlength); /* data length. */ -} - -/**************************************************************************** -Function called when the name lookup failed. -****************************************************************************/ - -static void wins_proxy_name_query_request_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, int fail_code) -{ - DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \ -of name %s.\n", fail_code, nmb_namestr(question_name) )); -} - -/**************************************************************************** -Function to make a deep copy of the userdata we will need when the WINS -proxy query returns. -****************************************************************************/ - -static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata) -{ - struct packet_struct *p, *copy_of_p; - struct userdata_struct *new_userdata = - (struct userdata_struct *)malloc( userdata->userdata_len ); - - if(new_userdata == NULL) - return NULL; - - new_userdata->copy_fn = userdata->copy_fn; - new_userdata->free_fn = userdata->free_fn; - new_userdata->userdata_len = userdata->userdata_len; - - /* Copy the subnet_record pointer. */ - memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) ); - - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); - - /* Do a deep copy of the packet. */ - if((copy_of_p = copy_packet(p)) == NULL) - { - SAFE_FREE(new_userdata); - return NULL; - } - - /* Lock the copy. */ - copy_of_p->locked = True; - - memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p, - sizeof(struct packet_struct *) ); - - return new_userdata; -} - -/**************************************************************************** -Function to free the deep copy of the userdata we used when the WINS -proxy query returned. -****************************************************************************/ - -static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata) -{ - struct packet_struct *p; - - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *)); - - /* Unlock the packet. */ - p->locked = False; - - free_packet(p); - ZERO_STRUCTP(userdata); - SAFE_FREE(userdata); -} - -/**************************************************************************** - Make a WINS query on behalf of a broadcast client name query request. -****************************************************************************/ - -void make_wins_proxy_name_query_request( struct subnet_record *subrec, - struct packet_struct *incoming_packet, - struct nmb_name *question_name) -{ - long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) + - sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - memset(ud, '\0', sizeof(ud)); - - userdata->copy_fn = wins_proxy_userdata_copy_fn; - userdata->free_fn = wins_proxy_userdata_free_fn; - userdata->userdata_len = sizeof(ud); - memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *)); - memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet, - sizeof(struct packet_struct *)); - - /* Now use the unicast subnet to query the name with the WINS server. */ - query_name( unicast_subnet, question_name->name, question_name->name_type, - wins_proxy_name_query_request_success, - wins_proxy_name_query_request_fail, - userdata); -} diff --git a/source4/nmbd/nmbd_winsserver.c b/source4/nmbd/nmbd_winsserver.c deleted file mode 100644 index 6d1f654e84..0000000000 --- a/source4/nmbd/nmbd_winsserver.c +++ /dev/null @@ -1,2032 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -#define WINS_LIST "wins.tdb" -#define WINS_VERSION 1 - -/**************************************************************************** -change the wins owner address in the record. -*****************************************************************************/ -static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) -{ - if (namerec==NULL) - return; - namerec->data.wins_ip=wins_ip; -} - -/**************************************************************************** -create the wins flags based on the nb flags and the input value. -*****************************************************************************/ -static void update_wins_flag(struct name_record *namerec, int flags) -{ - if (namerec==NULL) - return; - - namerec->data.wins_flags=0x0; - - /* if it's a group, it can be a normal or a special one */ - if (namerec->data.nb_flags & NB_GROUP) { - if (namerec->name.name_type==0x1C) - namerec->data.wins_flags|=WINS_SGROUP; - else - if (namerec->data.num_ips>1) - namerec->data.wins_flags|=WINS_SGROUP; - else - namerec->data.wins_flags|=WINS_NGROUP; - } else { - /* can be unique or multi-homed */ - if (namerec->data.num_ips>1) - namerec->data.wins_flags|=WINS_MHOMED; - else - namerec->data.wins_flags|=WINS_UNIQUE; - } - - /* the node type are the same bits */ - namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; - - /* the static bit is elsewhere */ - if (namerec->data.death_time == PERMANENT_TTL) - namerec->data.wins_flags|=WINS_STATIC; - - /* and add the given bits */ - namerec->data.wins_flags|=flags; - - DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", - namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags)); - -} - -/**************************************************************************** -return the general ID value and increase it if requested -*****************************************************************************/ -static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) -{ - /* - * it's kept as a static here, to prevent people from messing - * with the value directly - */ - - static SMB_BIG_UINT general_id = 1; - - DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id)); - - *current_id = general_id; - - if (update) - general_id++; -} - -/**************************************************************************** -possibly call the WINS hook external program when a WINS change is made -*****************************************************************************/ -static void wins_hook(const char *operation, struct name_record *namerec, int ttl) -{ - pstring command; - char *cmd = lp_wins_hook(); - char *p; - int i; - - if (!cmd || !*cmd) return; - - for (p=namerec->name.name; *p; p++) { - if (!(isalnum((int)*p) || strchr_m("._-",*p))) { - DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); - return; - } - } - - p = command; - p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", - cmd, - operation, - namerec->name.name, - namerec->name.name_type, - ttl); - - for (i=0;i<namerec->data.num_ips;i++) { - p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i])); - } - - DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); - smbrun(command, NULL); -} - - -/**************************************************************************** -Determine if this packet should be allocated to the WINS server. -*****************************************************************************/ - -BOOL packet_is_for_wins_server(struct packet_struct *packet) -{ - struct nmb_packet *nmb = &packet->packet.nmb; - - /* Only unicast packets go to a WINS server. */ - if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); - return False; - } - - /* Check for node status requests. */ - if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) - return False; - - switch(nmb->header.opcode) - { - /* - * A WINS server issues WACKS, not receives them. - */ - case NMB_WACK_OPCODE: - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); - return False; - /* - * A WINS server only processes registration and - * release requests, not responses. - */ - case NMB_NAME_REG_OPCODE: - case NMB_NAME_MULTIHOMED_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); - return False; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); - return False; - } - break; - - /* - * Only process unicast name queries with rd = 1. - */ - case NMB_NAME_QUERY_OPCODE: - if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); - return False; - } - break; - } - - return True; -} - -/**************************************************************************** -Utility function to decide what ttl to give a register/refresh request. -*****************************************************************************/ - -static int get_ttl_from_packet(struct nmb_packet *nmb) -{ - int ttl = nmb->additional->ttl; - - if(ttl < lp_min_wins_ttl() ) - ttl = lp_min_wins_ttl(); - - if(ttl > lp_max_wins_ttl() ) - ttl = lp_max_wins_ttl(); - - return ttl; -} - -/**************************************************************************** -Load or create the WINS database. -*****************************************************************************/ - -BOOL initialise_wins(void) -{ - time_t time_now = time(NULL); - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf, newkey; - struct name_record *namerec = NULL; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - DEBUG(2,("initialise_wins: started\n")); - - if(!lp_we_are_a_wins_server()) - return True; - - add_samba_names_to_subnet(wins_server_subnet); - - tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!tdb) { - DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); - return True; - } - - if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) { - DEBUG(0,("Discarding invalid wins.dat file\n")); - tdb_close(tdb); - return True; - } - - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - - fstring name_type; - pstring name, ip_str; - char *p; - int type = 0; - int nb_flags; - int ttl; - unsigned int num_ips; - int high, low; - struct in_addr wins_ip; - struct in_addr *ip_list; - int wins_flags; - int len,i; - - if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0) - continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; - - fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX)); - - pstrcpy(name, name_type); - - if((p = strchr(name,'#')) != NULL) { - *p = 0; - sscanf(p+1,"%x",&type); - } - - len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd", - &nb_flags, &high, &low, - ip_str, &ttl, &num_ips, &wins_flags); - - wins_ip=*interpret_addr2(ip_str); - - /* Don't reload replica records */ - if (!ip_equal(wins_ip, our_fake_ip)) { - SAFE_FREE(dbuf.dptr); - continue; - } - - /* Don't reload released or tombstoned records */ - if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) { - SAFE_FREE(dbuf.dptr); - continue; - } - - /* Allocate the space for the ip_list. */ - if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("initialise_wins: Malloc fail !\n")); - return False; - } - - for (i = 0; i < num_ips; i++) { - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str); - ip_list[i] = *interpret_addr2(ip_str); - } - - /* add all entries that have 60 seconds or more to live */ - if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { - if(ttl != PERMANENT_TTL) - ttl -= time_now; - - DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - - namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags, - ttl, REGISTER_NAME, num_ips, ip_list); - if (namerec!=NULL) { - update_wins_owner(namerec, wins_ip); - update_wins_flag(namerec, wins_flags); - /* we don't reload the ID, on startup we restart at 1 */ - get_global_id_and_update(&namerec->data.id, True); - } - - } else { - DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } - - SAFE_FREE(dbuf.dptr); - SAFE_FREE(ip_list); - } - - tdb_close(tdb); - DEBUG(2,("initialise_wins: done\n")); - return True; -} - -/**************************************************************************** -Send a WINS WACK (Wait ACKnowledgement) response. -**************************************************************************/ - -static void send_wins_wack_response(int ttl, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - unsigned char rdata[2]; - - rdata[0] = rdata[1] = 0; - - /* Taken from nmblib.c - we need to send back almost - identical bytes from the requesting packet header. */ - - rdata[0] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.nm_flags.authoritative && - nmb->header.response) rdata[0] |= 0x4; - if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2; - if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1; - if (nmb->header.nm_flags.recursion_available && - nmb->header.response) rdata[1] |= 0x80; - if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10; - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_WAIT_ACK, /* nmbd type code. */ - NMB_WACK_OPCODE, /* opcode. */ - ttl, /* ttl. */ - (char *)rdata, /* data to send. */ - 2); /* data length. */ -} - -/**************************************************************************** -Send a WINS name registration response. -**************************************************************************/ - -static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/*********************************************************************** - Deal with a name refresh request to a WINS server. -************************************************************************/ - -void wins_process_name_refresh_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = get_ttl_from_packet(nmb); - struct in_addr from_ip; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name refresh packets here. - * Anyone trying to refresh broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ -IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * If this is a refresh request and the name doesn't exist then - * treat it like a registration request. This allows us to recover - * from errors (tridge) - */ - - if(namerec == NULL) - { - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ -the name does not exist. Treating as registration.\n", nmb_namestr(question) )); - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * if the name is present but not active, - * simply remove it and treat the request - * as a registration - */ - if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ -not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * Check that the group bits for the refreshing name and the - * name in our database match. - */ - - if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) - { - DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ -does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * For a unique name check that the person refreshing the name is one of the registered IP - * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. - * Just return success for unique 0x1d refreshes. For normal group names update the ttl - * and return success. - */ - - if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) - { - /* - * Update the ttl. - */ - update_name_ttl(namerec, ttl); - - /* - * if the record is a replica: - * we take ownership and update the version ID. - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - update_wins_owner(namerec, our_fake_ip); - get_global_id_and_update(&namerec->data.id, True); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - else if(group) - { - /* - * Normal groups are all registered with an IP address of 255.255.255.255 - * so we can't search for the IP address. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else if(!group && (question->name_type == 0x1d)) - { - /* - * Special name type - just pretend the refresh succeeded. - */ - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * Fail the refresh. - */ - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ -is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } -} - -/*********************************************************************** - Deal with a name registration request query success to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. The success here is actually a failure as it means - the client we queried wants to keep the name, so we must return - a registration failure to the original requestor. -************************************************************************/ - -static void wins_register_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *question_name, - struct in_addr ip, - struct res_rec *answers) -{ - struct packet_struct *orig_reg_packet; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ -name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); - - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request query failure to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. The failure here is actually a success as it means - the client we queried didn't want to keep the name, so we can remove - the old name record and then successfully add the new name. -************************************************************************/ - -static void wins_register_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, - int rcode) -{ - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - struct name_record *namerec = NULL; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - /* - * We want to just add the name, as we now know the original owner - * didn't want it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this timeout/error response. So we check that - * the name still exists and is in the same state - if so - * we remove it and call wins_process_name_registration_request() - * as we know it will do the right thing now. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec != NULL) - && (namerec->data.source == REGISTER_NAME) - && ip_equal(rrec->packet->ip, *namerec->data.ip) ) - { - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - if(namerec == NULL) - wins_process_name_registration_request(subrec, orig_reg_packet); - else - DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ -querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request to a WINS server. - - Use the following pseudocode : - - registering_group - | - | - +--------name exists - | | - | | - | +--- existing name is group - | | | - | | | - | | +--- add name (return). - | | - | | - | +--- exiting name is unique - | | - | | - | +--- query existing owner (return). - | - | - +--------name doesn't exist - | - | - +--- add name (return). - - registering_unique - | - | - +--------name exists - | | - | | - | +--- existing name is group - | | | - | | | - | | +--- fail add (return). - | | - | | - | +--- exiting name is unique - | | - | | - | +--- query existing owner (return). - | - | - +--------name doesn't exist - | - | - +--- add name (return). - - As can be seen from the above, the two cases may be collapsed onto each - other with the exception of the case where the name already exists and - is a group name. This case we handle with an if statement. - -************************************************************************/ - -void wins_process_name_registration_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ -IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ -not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ -a dns lookup - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) - { - DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ -to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Special policy decisions based on MS documentation. - * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. - * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. - */ - - /* - * A group name is always added as the local broadcast address, except - * for group names ending in 0x1c. - * Group names with type 0x1c are registered with individual IP addresses. - */ - - if(registering_group_name && (question->name_type != 0x1c)) - from_ip = *interpret_addr2("255.255.255.255"); - - /* - * Ignore all attempts to register a unique 0x1d name, although return success. - */ - - if(!registering_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_registration_request: Ignoring request \ -to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * Next two cases are the 'if statement' mentioned above. - */ - - if((namerec != NULL) && NAME_GROUP(namerec)) - { - if(registering_group_name) - { - /* - * If we are adding a group name, the name exists and is also a group entry just add this - * IP address to it and update the ttl. - */ - - DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", - inet_ntoa(from_ip), nmb_namestr(question) )); - /* - * Check the ip address is not already in the group. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - add_ip_to_name_record(namerec, from_ip); - /* we need to update the record for replication */ - get_global_id_and_update(&namerec->data.id, True); - - /* - * if the record is a replica, we must change - * the wins owner to us to make the replication updates - * it on the other wins servers. - * And when the partner will receive this record, - * it will update its own record. - */ - - update_wins_owner(namerec, our_fake_ip); - - } - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * If we are adding a unique name, the name exists in the WINS db - * and is a group name then reject the registration. - * - * explanation: groups have a higher priority than unique names. - */ - - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ -already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ -is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's - update the ttl. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - } - - /* - * If the name exists and it is a unique registration and the registering IP - * is the same as the (single) already registered IP then just update the ttl. - * - * But not if the record is an active replica. IF it's a replica, it means it can be - * the same client which has moved and not yet expired. So we don't update - * the ttl in this case and go beyond to do a WACK and query the old client - */ - - if( !registering_group_name - && (namerec != NULL) - && (namerec->data.num_ips == 1) - && ip_equal( namerec->data.ip[0], from_ip ) - && ip_equal(namerec->data.wins_ip, our_fake_ip) ) - { - update_name_ttl( namerec, ttl ); - send_wins_name_registration_response( 0, ttl, p ); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * Finally if the name exists do a query to the registering machine - * to see if they still claim to have the name. - */ - - if( namerec != NULL ) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - */ - - query_name_from_wins_server( *namerec->data.ip, - question->name, - question->name_type, - wins_register_query_success, - wins_register_query_fail, - userdata ); - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } - - send_wins_name_registration_response(0, ttl, p); -} - -/*********************************************************************** - Deal with a mutihomed name query success to the machine that - requested the multihomed name registration. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. -************************************************************************/ - -static void wins_multihomed_register_query_success(struct subnet_record *subrec, - struct userdata_struct *userdata, - struct nmb_name *question_name, - struct in_addr ip, - struct res_rec *answers) -{ - struct packet_struct *orig_reg_packet; - struct nmb_packet *nmb; - struct name_record *namerec = NULL; - struct in_addr from_ip; - int ttl; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - nmb = &orig_reg_packet->packet.nmb; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ttl = get_ttl_from_packet(nmb); - - /* - * We want to just add the new IP, as we now know the requesting - * machine claims to own it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this response. So we check that - * the name still exists and is in the same state - if so - * we just add the extra IP and update the ttl. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) - { - DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ -a subsequent IP address.\n", nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - - return; - } - - if(!find_ip_in_name_record(namerec, from_ip)) - add_ip_to_name_record(namerec, from_ip); - - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, orig_reg_packet); - wins_hook("add", namerec, ttl); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); -} - -/*********************************************************************** - Deal with a name registration request query failure to a client that - owned the name. - - We have a locked pointer to the original packet stashed away in the - userdata pointer. -************************************************************************/ - -static void wins_multihomed_register_query_fail(struct subnet_record *subrec, - struct response_record *rrec, - struct nmb_name *question_name, - int rcode) -{ - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ -query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - return; -} - -/*********************************************************************** - Deal with a multihomed name registration request to a WINS server. - These cannot be group name registrations. -***********************************************************************/ - -void wins_process_multihomed_name_registration_request( struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - /* - * Only unique names should be registered multihomed. - */ - - if(group) - { - DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ -received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ -IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * Deal with policy regarding 0x1d names. - */ - - if(question->name_type == 0x1d) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ -to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); - remove_name_from_namelist(subrec, namerec); - namerec = NULL; - } - - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ -- removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) - { - DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ -to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Reject if the name exists and is a GROUP name and is active. - */ - - if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ -already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ -is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's. Ensure the IP is in the record and - * update the ttl. Update the version ID to force replication. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - - add_ip_to_name_record(namerec, from_ip); - wins_hook("add", namerec, ttl); - } else { - wins_hook("refresh", namerec, ttl); - } - - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - } - - /* - * If the name exists and is active, check if the IP address is already registered - * to that name. If so then update the ttl and reply success. - */ - - if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) - { - update_name_ttl(namerec, ttl); - /* - * If it's a replica, we need to become the wins owner - * to force the replication - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * If the name exists do a query to the owner - * to see if they still want the name. - */ - - if(namerec != NULL) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - * - * Note that this packet is sent to the current owner of the name, - * not the person who sent the packet - */ - - query_name_from_wins_server( namerec->data.ip[0], - question->name, - question->name_type, - wins_multihomed_register_query_success, - wins_multihomed_register_query_fail, - userdata ); - - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } - - send_wins_name_registration_response(0, ttl, p); -} - -/*********************************************************************** - Deal with the special name query for *<1b>. -***********************************************************************/ - -static void process_wins_dmb_query_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct name_record *namerec = NULL; - char *prdata; - int num_ips; - - /* - * Go through all the ACTIVE names in the WINS db looking for those - * ending in <1b>. Use this to calculate the number of IP - * addresses we need to return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) - num_ips += namerec->data.num_ips; - } - - if(num_ips == 0) - { - /* - * There are no 0x1b names registered. Return name query fail. - */ - send_wins_name_query_response(NAM_ERR, p, NULL); - return; - } - - if((prdata = (char *)malloc( num_ips * 6 )) == NULL) - { - DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); - return; - } - - /* - * Go through all the names again in the WINS db looking for those - * ending in <1b>. Add their IP addresses into the list we will - * return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) - { - int i; - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); - putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); - num_ips++; - } - } - } - - /* - * Send back the reply containing the IP list. - */ - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - lp_min_wins_ttl(), /* ttl. */ - prdata, /* data to send. */ - num_ips*6); /* data length. */ - - SAFE_FREE(prdata); -} - -/**************************************************************************** -Send a WINS name query response. -**************************************************************************/ - -void send_wins_name_query_response(int rcode, struct packet_struct *p, - struct name_record *namerec) -{ - char rdata[6]; - char *prdata = rdata; - int reply_data_len = 0; - int ttl = 0; - int i; - - memset(rdata,'\0',6); - - if(rcode == 0) - { - ttl = (namerec->data.death_time != PERMANENT_TTL) ? - namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); - - /* Copy all known ip addresses into the return data. */ - /* Optimise for the common case of one IP address so - we don't need a malloc. */ - - if( namerec->data.num_ips == 1 ) - prdata = rdata; - else - { - if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) - { - DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); - return; - } - } - - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[i*6],namerec->data.nb_flags); - putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); - } - - sort_query_replies(prdata, i, p->ip); - - reply_data_len = namerec->data.num_ips * 6; - } - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - prdata, /* data to send. */ - reply_data_len); /* data length. */ - - if(prdata != rdata) - SAFE_FREE(prdata); -} - -/*********************************************************************** - Deal with a name query. -***********************************************************************/ - -void wins_process_name_query_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - struct name_record *namerec = NULL; - - DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", - nmb_namestr(question), inet_ntoa(p->ip) )); - - /* - * Special name code. If the queried name is *<1b> then search - * the entire WINS database and return a list of all the IP addresses - * registered to any <1b> name. This is to allow domain master browsers - * to discover other domains that may not have a presence on their subnet. - */ - - if(strequal( question->name, "*") && (question->name_type == 0x1b)) - { - process_wins_dmb_query_request( subrec, p); - return; - } - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if(namerec != NULL) - { - /* - * If the name is not anymore in active state then reply not found. - * it's fair even if we keep it in the cache for days. - */ - if (!WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - /* - * If it's a DNSFAIL_NAME then reply name not found. - */ - - if( namerec->data.source == DNSFAIL_NAME ) - { - DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - /* - * If the name has expired then reply name not found. - */ - - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < p->timestamp) ) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", - nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); - - send_wins_name_query_response(0, p, namerec); - return; - } - - /* - * Name not found in WINS - try a dns query if it's a 0x20 name. - */ - - if(lp_dns_proxy() && - ((question->name_type == 0x20) || question->name_type == 0)) - { - - DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", - nmb_namestr(question) )); - - queue_dns_query(p, question, &namerec); - return; - } - - /* - * Name not found - return error. - */ - - send_wins_name_query_response(NAM_ERR, p, NULL); -} - -/**************************************************************************** -Send a WINS name release response. -**************************************************************************/ - -static void send_wins_name_release_response(int rcode, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REL, /* nmbd type code. */ - NMB_NAME_RELEASE_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ -} - -/*********************************************************************** - Deal with a name release. -***********************************************************************/ - -void wins_process_name_release_request(struct subnet_record *subrec, - struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ -received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - - DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ -IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - - /* - * Deal with policy regarding 0x1d names. - */ - - if(!releasing_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_release_request: Ignoring request \ -to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_release_response(0, p); - return; - } - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if( (namerec == NULL) - || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) - { - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check that the sending machine has permission to release this name. - * If it's a group name not ending in 0x1c then just say yes and let - * the group time out. - */ - - if(releasing_group_name && (question->name_type != 0x1c)) - { - send_wins_name_release_response(0, p); - return; - } - - /* - * Check that the releasing node is on the list of IP addresses - * for this name. Disallow the release if not. - */ - - if(!find_ip_in_name_record(namerec, from_ip)) - { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as IP %s is not one of the known IP's for this name.\n", - nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is active. IF it's already released - * or tombstoned, refuse the release. - */ - if (!WINS_STATE_ACTIVE(namerec)) { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as this record is not anymore active.\n", - nmb_namestr(question) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is a 0x1c group - * and has more then one ip - * remove only this address. - */ - - if(releasing_group_name && - (question->name_type == 0x1c) && - (namerec->data.num_ips > 1)) { - remove_ip_from_name_record(namerec, from_ip); - DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", - inet_ntoa(from_ip),nmb_namestr(question))); - send_wins_name_release_response(0, p); - return; - } - - /* - * Send a release response. - * Flag the name as released and update the ttl - */ - - send_wins_name_release_response(0, p); - - namerec->data.wins_flags |= WINS_RELEASED; - update_name_ttl(namerec, EXTINCTION_INTERVAL); - - wins_hook("delete", namerec, 0); -} - -/******************************************************************* - WINS time dependent processing. -******************************************************************/ - -void initiate_wins_processing(time_t t) -{ - static time_t lasttime = 0; - struct name_record *namerec; - struct name_record *next_namerec; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - if (!lasttime) - lasttime = t; - if (t - lasttime < 20) - return; - - lasttime = t; - - if(!lp_we_are_a_wins_server()) - return; - - for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = next_namerec ) { - next_namerec = (struct name_record *)ubi_trNext( namerec ); - - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < t) ) { - - if( namerec->data.source == SELF_NAME ) { - DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", - wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - namerec->subnet->namelist_changed = True; - continue; - } - - /* handle records, samba is the wins owner */ - if (ip_equal(namerec->data.wins_ip, our_fake_ip)) { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_RELEASED; - namerec->data.death_time = t + EXTINCTION_INTERVAL; - DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name))); - break; - case WINS_RELEASED: - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - get_global_id_and_update(&namerec->data.id, True); - DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); - break; - case WINS_TOMBSTONED: - DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); - remove_name_from_namelist( wins_server_subnet, namerec ); - break; - } - } else { - switch (namerec->data.wins_flags | WINS_STATE_MASK) { - case WINS_ACTIVE: - /* that's not as MS says it should be */ - namerec->data.wins_flags&=~WINS_STATE_MASK; - namerec->data.wins_flags|=WINS_TOMBSTONED; - namerec->data.death_time = t + EXTINCTION_TIMEOUT; - DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name))); - case WINS_TOMBSTONED: - DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name))); - remove_name_from_namelist( wins_server_subnet, namerec ); - break; - case WINS_RELEASED: - DEBUG(0,("initiate_wins_processing: %s is in released state and\ -we are not the wins owner !\n", nmb_namestr(&namerec->name))); - break; - } - } - - } - } - - if(wins_server_subnet->namelist_changed) - wins_write_database(True); - - wins_server_subnet->namelist_changed = False; -} - -/******************************************************************* - Write out the current WINS database. -******************************************************************/ -void wins_write_database(BOOL background) -{ - struct name_record *namerec; - pstring fname, fnamenew; - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf; - pstring key, buf; - int len; - int num_record=0; - SMB_BIG_UINT id; - - if(!lp_we_are_a_wins_server()) - return; - - /* we will do the writing in a child process to ensure that the parent - doesn't block while this is done */ - if (background) { - CatchChild(); - if (sys_fork()) { - return; - } - } - - slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); - all_string_sub(fname,"//", "/", 0); - slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - - tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644); - if (!tdb) { - DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); - if (background) - _exit(0); - return; - } - - DEBUG(3,("wins_write_database: Dump of WINS name list.\n")); - - tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION); - - for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) { - - int i; - struct tm *tm; - - DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) )); - - if( namerec->data.death_time != PERMANENT_TTL ) { - char *ts, *nl; - - tm = localtime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr_m( ts, '\n' ); - if( NULL != nl ) - *nl = '\0'; - - DEBUGADD(3,("TTL = %s ", ts )); - } else - DEBUGADD(3,("TTL = PERMANENT ")); - - for (i = 0; i < namerec->data.num_ips; i++) - DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) )); - - DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip))); - - if( namerec->data.source == REGISTER_NAME ) { - - /* store the type in the key to make the name unique */ - slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type); - - len = tdb_pack(buf, sizeof(buf), "dddfddd", - (int)namerec->data.nb_flags, - (int)(namerec->data.id>>32), - (int)(namerec->data.id&0xffffffff), - inet_ntoa(namerec->data.wins_ip), - (int)namerec->data.death_time, - namerec->data.num_ips, - namerec->data.wins_flags); - - for (i = 0; i < namerec->data.num_ips; i++) - len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i])); - - kbuf.dsize = strlen(key)+1; - kbuf.dptr = key; - dbuf.dsize = len; - dbuf.dptr = buf; - if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return; - - num_record++; - } - } - - /* store the number of records */ - tdb_store_int32(tdb, INFO_COUNT, num_record); - - /* get and store the last used ID */ - get_global_id_and_update(&id, False); - tdb_store_int32(tdb, INFO_ID_HIGH, id>>32); - tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff); - - tdb_close(tdb); - - chmod(fnamenew,0644); - unlink(fname); - rename(fnamenew,fname); - - if (background) - _exit(0); -} - -/**************************************************************************** -process a internal Samba message receiving a wins record -***************************************************************************/ -void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) -{ - WINS_RECORD *record; - struct name_record *namerec = NULL; - struct name_record *new_namerec = NULL; - struct nmb_name question; - BOOL overwrite=False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - int i; - - if (buf==NULL) - return; - - record=(WINS_RECORD *)buf; - - ZERO_STRUCT(question); - memcpy(question.name, record->name, 16); - question.name_type=record->type; - - namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); - - /* record doesn't exist, add it */ - if (namerec == NULL) { - DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - - new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, - EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); - if (new_namerec!=NULL) { - update_wins_owner(new_namerec, record->wins_ip); - update_wins_flag(new_namerec, record->wins_flags); - new_namerec->data.id=record->id; - - wins_server_subnet->namelist_changed = True; - } - } - - /* check if we have a conflict */ - if (namerec != NULL) { - /* both records are UNIQUE */ - if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) { - - /* the database record is a replica */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) { - if (ip_equal(namerec->data.wins_ip, record->wins_ip)) - overwrite=True; - } else - overwrite=True; - } else { - /* we are the wins owner of the database record */ - /* the 2 records have the same IP address */ - if (ip_equal(namerec->data.ip[0], record->ip[0])) { - if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) - get_global_id_and_update(&namerec->data.id, True); - else - overwrite=True; - - } else { - /* the 2 records have different IP address */ - if (namerec->data.wins_flags&WINS_ACTIVE) { - if (record->wins_flags&WINS_TOMBSTONED) - get_global_id_and_update(&namerec->data.id, True); - if (record->wins_flags&WINS_ACTIVE) - /* send conflict challenge to the replica node */ - ; - } else - overwrite=True; - } - - } - } - - /* the replica is a standard group */ - if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) { - /* if the database record is unique and active force a name release */ - if (namerec->data.wins_flags&WINS_UNIQUE) - /* send a release name to the unique node */ - ; - overwrite=True; - - } - - /* the replica is a special group */ - if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) { - if (namerec->data.wins_flags&WINS_ACTIVE) { - for (i=0; i<record->num_ips; i++) - if(!find_ip_in_name_record(namerec, record->ip[i])) - add_ip_to_name_record(namerec, record->ip[i]); - } - else - overwrite=True; - } - - /* the replica is a multihomed host */ - - /* I'm giving up on multi homed. Too much complex to understand */ - - if (record->wins_flags&WINS_MHOMED) { - if (! (namerec->data.wins_flags&WINS_ACTIVE)) { - if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP)) - overwrite=True; - } - else { - if (ip_equal(record->wins_ip, namerec->data.wins_ip)) - overwrite=True; - - if (ip_equal(namerec->data.wins_ip, our_fake_ip)) - if (namerec->data.wins_flags&WINS_UNIQUE) - get_global_id_and_update(&namerec->data.id, True); - - } - - if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE) - if (namerec->data.wins_flags&WINS_UNIQUE || - namerec->data.wins_flags&WINS_MHOMED) - if (ip_equal(record->wins_ip, namerec->data.wins_ip)) - overwrite=True; - - } - - if (overwrite == False) - DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - else { - DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", - record->name, record->type, inet_ntoa(record->wins_ip))); - - /* remove the old record and add a new one */ - remove_name_from_namelist( wins_server_subnet, namerec ); - new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, - EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip); - if (new_namerec!=NULL) { - update_wins_owner(new_namerec, record->wins_ip); - update_wins_flag(new_namerec, record->wins_flags); - new_namerec->data.id=record->id; - - wins_server_subnet->namelist_changed = True; - } - - wins_server_subnet->namelist_changed = True; - } - - } -} - - - - - - - - diff --git a/source4/nmbd/nmbd_workgroupdb.c b/source4/nmbd/nmbd_workgroupdb.c deleted file mode 100644 index 3e177bceb4..0000000000 --- a/source4/nmbd/nmbd_workgroupdb.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1998 - Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 - - 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" - -extern int ClientNMB; - -extern uint16 samba_nb_type; - -int workgroup_count = 0; /* unique index key: one for each workgroup */ - -/**************************************************************************** - Add a workgroup into the list. - **************************************************************************/ - -static void add_workgroup(struct subnet_record *subrec, struct work_record *work) -{ - work->subnet = subrec; - DLIST_ADD(subrec->workgrouplist, work); - subrec->work_changed = True; -} - -/**************************************************************************** - Create an empty workgroup. - **************************************************************************/ - -static struct work_record *create_workgroup(const char *name, int ttl) -{ - struct work_record *work; - struct subnet_record *subrec; - int t = -1; - - if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) - { - DEBUG(0,("create_workgroup: malloc fail !\n")); - return NULL; - } - memset((char *)work, '\0', sizeof(*work)); - - StrnCpy(work->work_group,name,sizeof(work->work_group)-1); - work->serverlist = NULL; - - work->RunningElection = False; - work->ElectionCount = 0; - work->announce_interval = 0; - work->needelection = False; - work->needannounce = True; - work->lastannounce_time = time(NULL); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - work->dom_state = DOMAIN_NONE; - work->log_state = LOGON_NONE; - - work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - - /* Make sure all token representations of workgroups are unique. */ - - for (subrec = FIRST_SUBNET; subrec && (t == -1); - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *w; - for (w = subrec->workgrouplist; w && t == -1; w = w->next) - { - if (strequal(w->work_group, work->work_group)) - t = w->token; - } - } - - if (t == -1) - work->token = ++workgroup_count; - else - work->token = t; - - /* No known local master browser as yet. */ - *work->local_master_browser_name = '\0'; - - /* No known domain master browser as yet. */ - *work->dmb_name.name = '\0'; - zero_ip(&work->dmb_addr); - - /* WfWg uses 01040b01 */ - /* Win95 uses 01041501 */ - /* NTAS uses ???????? */ - work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); - work->ElectionCriterion |= (lp_os_level() << 24); - if (lp_domain_master()) - work->ElectionCriterion |= 0x80; - - return work; -} - -/******************************************************************* - Remove a workgroup. - ******************************************************************/ - -static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec, - struct work_record *work) -{ - struct work_record *ret_work = NULL; - - DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group)); - - ret_work = work->next; - - remove_all_servers(work); - - if (!work->serverlist) - { - if (work->prev) - work->prev->next = work->next; - if (work->next) - work->next->prev = work->prev; - - if (subrec->workgrouplist == work) - subrec->workgrouplist = work->next; - - ZERO_STRUCTP(work); - SAFE_FREE(work); - } - - subrec->work_changed = True; - - return ret_work; -} - - -/**************************************************************************** - Find a workgroup in the workgroup list of a subnet. - **************************************************************************/ - -struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec, - const char *name) -{ - struct work_record *ret; - - DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ", - name, subrec->subnet_name)); - - for (ret = subrec->workgrouplist; ret; ret = ret->next) - { - if (!strcmp(ret->work_group,name)) - { - DEBUGADD(4, ("found.\n")); - return(ret); - } - } - DEBUGADD(4, ("not found.\n")); - return NULL; -} - -/**************************************************************************** - Create a workgroup in the workgroup list of the subnet. - **************************************************************************/ - -struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec, - const char *name, int ttl) -{ - struct work_record *work = NULL; - - DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", - name, subrec->subnet_name)); - - if ((work = create_workgroup(name, ttl))) - { - add_workgroup(subrec, work); - - subrec->work_changed = True; - - return(work); - } - - return NULL; -} - -/**************************************************************************** - Update a workgroup ttl. - **************************************************************************/ - -void update_workgroup_ttl(struct work_record *work, int ttl) -{ - if(work->death_time != PERMANENT_TTL) - work->death_time = time(NULL)+(ttl*3); - work->subnet->work_changed = True; -} - -/**************************************************************************** - Fail function called if we cannot register the WORKGROUP<0> and - WORKGROUP<1e> names on the net. -**************************************************************************/ - -static void fail_register(struct subnet_record *subrec, struct response_record *rrec, - struct nmb_name *nmbname) -{ - DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); -} - -/**************************************************************************** - If the workgroup is our primary workgroup, add the required names to it. -**************************************************************************/ - -void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work) -{ - int i; - - if(!strequal(lp_workgroup(), work->work_group)) - return; - - /* If this is a broadcast subnet then start elections on it - if we are so configured. */ - - if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && - (subrec != wins_server_subnet) && lp_preferred_master() && - lp_local_master()) - { - DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \ -workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } - - /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */ - - register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - for( i = 0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - int stype = lp_default_server_announce() | (lp_local_master() ? - SV_TYPE_POTENTIAL_BROWSER : 0 ); - - if(!strequal(lp_netbios_name(), name)) - stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER| - SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); - - create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, - PERMANENT_TTL, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \ -on subnet %s\n", name, subrec->subnet_name)); - } -} - -/**************************************************************************** - Dump a copy of the workgroup database into the log file. - **************************************************************************/ - -void dump_workgroups(BOOL force_write) -{ - struct subnet_record *subrec; - int debuglevel = force_write ? 0 : 4; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if (subrec->workgrouplist) - { - struct work_record *work; - - if( DEBUGLVL( debuglevel ) ) - { - dbgtext( "dump_workgroups()\n " ); - dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name ); - dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) ); - } - - for (work = subrec->workgrouplist; work; work = work->next) - { - DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", - work->work_group, - work->token, - *work->local_master_browser_name - ? work->local_master_browser_name : "UNKNOWN" ) ); - if (work->serverlist) - { - struct server_record *servrec; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n", - servrec->serv.name, - servrec->serv.type, - servrec->serv.comment ) ); - } - } - } - } - } -} - -/**************************************************************************** - Expire any dead servers on all workgroups. If the workgroup has expired - remove it. - **************************************************************************/ - -void expire_workgroups_and_servers(time_t t) -{ - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work; - struct work_record *nextwork; - - for (work = subrec->workgrouplist; work; work = nextwork) - { - nextwork = work->next; - expire_servers(work, t); - - if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) && - ((t == -1) || (work->death_time < t))) - { - DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n", - work->work_group)); - remove_workgroup_from_subnet(subrec, work); - } - } - } -} diff --git a/source4/nsswitch/README b/source4/nsswitch/README deleted file mode 100644 index 9f0c581df6..0000000000 --- a/source4/nsswitch/README +++ /dev/null @@ -1,13 +0,0 @@ -This extension provides a "wins" module for NSS on glibc2/Linux. This -allows you to use a WINS entry in /etc/nsswitch.conf for hostname -resolution, allowing you to resolve netbios names via start unix -gethostbyname() calls. The end result is that you can use netbios -names as host names in unix apps. - -1) run configure -2) run "make nsswitch" -3) cp nsswitch/libnss_wins.so /lib/libnss_wins.so.2 -4) add a wins entry to the hosts line in /etc/nsswitch.conf -5) use it - -tridge@linuxcare.com diff --git a/source4/nsswitch/config.m4 b/source4/nsswitch/config.m4 deleted file mode 100644 index 2d5efe0eb6..0000000000 --- a/source4/nsswitch/config.m4 +++ /dev/null @@ -1,105 +0,0 @@ -################################################# -# Check whether winbind is supported on this platform. If so we need to -# build and install client programs, sbin programs and shared libraries - -AC_MSG_CHECKING(whether to build winbind) - -# Initially, the value of $host_os decides whether winbind is supported - -case "$host_os" in - *linux*|*irix*) - HAVE_WINBIND=yes - ;; - *solaris*) - HAVE_WINBIND=yes - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" - WINBIND_NSS_EXTRA_LIBS="-lsocket" - ;; - *hpux11*) - HAVE_WINBIND=yes - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" - ;; - *) - HAVE_WINBIND=no - winbind_no_reason=", unsupported on $host_os" - ;; -esac - -AC_SUBST(WINBIND_NSS_EXTRA_OBJS) -AC_SUBST(WINBIND_NSS_EXTRA_LIBS) - -# Check the setting of --with-winbindd - -AC_ARG_WITH(winbind, -[ --with-winbind Build winbind (default, if supported by OS)], -[ - case "$withval" in - yes) - HAVE_WINBIND=yes - ;; - no) - HAVE_WINBIND=no - winbind_reason="" - ;; - esac ], -) - -# We need unix domain sockets for winbind -if test x"$HAVE_WINBIND" = x"yes"; then - if test x"$samba_cv_unixsocket" = x"no"; then - winbind_no_reason=", no unix domain socket support on $host_os" - HAVE_WINBIND=no - fi -fi - -# Display test results - -if test x"$HAVE_WINBIND" = x"yes"; then - AC_MSG_RESULT(yes) - AC_DEFINE(WITH_WINBIND,1,[Whether to build winbind]) - - EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/wbinfo\$(EXEEXT)" - EXTRA_SBIN_PROGS="$EXTRA_SBIN_PROGS bin/winbindd\$(EXEEXT)" - if test x"$BLDSHARED" = x"true"; then - case "$host_os" in - *irix*) - SHLIB_PROGS="$SHLIB_PROGS nsswitch/libns_winbind.so" - ;; - *) - SHLIB_PROGS="$SHLIB_PROGS nsswitch/libnss_winbind.so" - ;; - esac - if test x"$with_pam" = x"yes"; then - SHLIB_PROGS="$SHLIB_PROGS nsswitch/pam_winbind.so" - fi - fi -else - AC_MSG_RESULT(no$winbind_no_reason) -fi - -# Solaris has some extra fields in struct passwd that need to be -# initialised otherwise nscd crashes. Unfortunately autoconf < 2.50 -# doesn't have the AC_CHECK_MEMBER macro which would be handy for checking -# this. - -#AC_CHECK_MEMBER(struct passwd.pw_comment, -# AC_DEFINE(HAVE_PASSWD_PW_COMMENT, 1, [Defined if struct passwd has pw_comment field]), -# [#include <pwd.h>]) - -AC_CACHE_CHECK([whether struct passwd has pw_comment],samba_cv_passwd_pw_comment, [ - AC_TRY_COMPILE([#include <pwd.h>],[struct passwd p; p.pw_comment;], - samba_cv_passwd_pw_comment=yes,samba_cv_passwd_pw_comment=no)]) -if test x"$samba_cv_passwd_pw_comment" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_COMMENT,1,[Whether struct passwd has pw_comment]) -fi - -#AC_CHECK_MEMBER(struct passwd.pw_age, -# AC_DEFINE(HAVE_PASSWD_PW_AGE, 1, [Defined if struct passwd has pw_age field]), -# [#include <pwd.h>]) - -AC_CACHE_CHECK([whether struct passwd has pw_age],samba_cv_passwd_pw_age, [ - AC_TRY_COMPILE([#include <pwd.h>],[struct passwd p; p.pw_age;], - samba_cv_passwd_pw_age=yes,samba_cv_passwd_pw_age=no)]) -if test x"$samba_cv_passwd_pw_age" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_AGE,1,[Whether struct passwd has pw_age]) -fi diff --git a/source4/nsswitch/hp_nss_common.h b/source4/nsswitch/hp_nss_common.h deleted file mode 100644 index 5bd5374182..0000000000 --- a/source4/nsswitch/hp_nss_common.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _HP_NSS_COMMON_H -#define _HP_NSS_COMMON_H - -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifdef HAVE_SYNCH_H -#include <synch.h> -#endif -#ifdef HAVE_PTHREAD_H -#include <pthread.h> -#endif - -typedef enum { - NSS_SUCCESS, - NSS_NOTFOUND, - NSS_UNAVAIL, - NSS_TRYAGAIN -} nss_status_t; - -struct nss_backend; - -typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); - -struct nss_backend { - nss_backend_op_t *ops; - int n_ops; -}; -typedef struct nss_backend nss_backend_t; -typedef int nss_dbop_t; - -#endif /* _HP_NSS_COMMON_H */ diff --git a/source4/nsswitch/hp_nss_dbdefs.h b/source4/nsswitch/hp_nss_dbdefs.h deleted file mode 100644 index bd24772e33..0000000000 --- a/source4/nsswitch/hp_nss_dbdefs.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _HP_NSS_DBDEFS_H -#define _HP_NSS_DBDEFS_H - -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include <errno.h> -#include <netdb.h> -#include <limits.h> - -#ifndef NSS_INCLUDE_UNSAFE -#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ -#endif /* NSS_INCLUDE_UNSAFE */ - -enum nss_netgr_argn { - NSS_NETGR_MACHINE, - NSS_NETGR_USER, - NSS_NETGR_DOMAIN, - NSS_NETGR_N -}; - -enum nss_netgr_status { - NSS_NETGR_FOUND, - NSS_NETGR_NO, - NSS_NETGR_NOMEM -}; - -typedef unsigned nss_innetgr_argc; -typedef char **nss_innetgr_argv; - -struct nss_innetgr_1arg { - nss_innetgr_argc argc; - nss_innetgr_argv argv; -}; - -typedef struct { - void *result; /* "result" parameter to getXbyY_r() */ - char *buffer; /* "buffer" " " */ - int buflen; /* "buflen" " " */ -} nss_XbyY_buf_t; - -extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); -extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); - -union nss_XbyY_key { - uid_t uid; - gid_t gid; - const char *name; - int number; - struct { - long net; - int type; - } netaddr; - struct { - const char *addr; - int len; - int type; - } hostaddr; - struct { - union { - const char *name; - int port; - } serv; - const char *proto; - } serv; - void *ether; -}; - -typedef struct nss_XbyY_args { - nss_XbyY_buf_t buf; - int stayopen; - /* - * Support for setXXXent(stayopen) - * Used only in hosts, protocols, - * networks, rpc, and services. - */ - int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); - union nss_XbyY_key key; - - void *returnval; - int erange; - int h_errno; - nss_status_t status; -} nss_XbyY_args_t; - -#endif /* _NSS_DBDEFS_H */ diff --git a/source4/nsswitch/nss.h b/source4/nsswitch/nss.h deleted file mode 100644 index d83a5e237e..0000000000 --- a/source4/nsswitch/nss.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef _NSSWITCH_NSS_H -#define _NSSWITCH_NSS_H -/* - Unix SMB/CIFS implementation. - - a common place to work out how to define NSS_STATUS on various - platforms - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifdef HAVE_NSS_COMMON_H - -/* Sun Solaris */ - -#include <nss_common.h> -#include <nss_dbdefs.h> -#include <nsswitch.h> - -typedef nss_status_t NSS_STATUS; - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -#elif HAVE_NSS_H - -/* GNU */ - -#include <nss.h> - -typedef enum nss_status NSS_STATUS; - -#elif HAVE_NS_API_H - -/* SGI IRIX */ - -/* following required to prevent warnings of double definition - * of datum from ns_api.h -*/ -#ifdef DATUM -#define _DATUM_DEFINED -#endif - -#include <ns_api.h> - -typedef enum -{ - NSS_STATUS_SUCCESS=NS_SUCCESS, - NSS_STATUS_NOTFOUND=NS_NOTFOUND, - NSS_STATUS_UNAVAIL=NS_UNAVAIL, - NSS_STATUS_TRYAGAIN=NS_TRYAGAIN -} NSS_STATUS; - -#define NSD_MEM_STATIC 0 -#define NSD_MEM_VOLATILE 1 -#define NSD_MEM_DYNAMIC 2 - -#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) -/* HP-UX 11 */ - -#include "nsswitch/hp_nss_common.h" -#include "nsswitch/hp_nss_dbdefs.h" -#include <nsswitch.h> - -#ifndef _HAVE_TYPEDEF_NSS_STATUS -#define _HAVE_TYPEDEF_NSS_STATUS -typedef nss_status_t NSS_STATUS; - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN -#endif /* HPUX */ - -#else /* Nothing's defined. Neither gnu nor sun nor hp */ - -typedef enum -{ - NSS_STATUS_SUCCESS=0, - NSS_STATUS_NOTFOUND=1, - NSS_STATUS_UNAVAIL=2, - NSS_STATUS_TRYAGAIN=3 -} NSS_STATUS; - -#endif - -#endif /* _NSSWITCH_NSS_H */ diff --git a/source4/nsswitch/pam_winbind.c b/source4/nsswitch/pam_winbind.c deleted file mode 100644 index 123f670366..0000000000 --- a/source4/nsswitch/pam_winbind.c +++ /dev/null @@ -1,754 +0,0 @@ -/* pam_winbind module - - Copyright Andrew Tridgell <tridge@samba.org> 2000 - Copyright Tim Potter <tpot@samba.org> 2000 - Copyright Andrew Bartlett <abartlet@samba.org> 2002 - - largely based on pam_userdb by Christian Gafton <gafton@redhat.com> - also contains large slabs of code from pam_unix by Elliot Lee <sopwith@redhat.com> - (see copyright below for full details) -*/ - -#include "pam_winbind.h" - -/* data tokens */ - -#define MAX_PASSWD_TRIES 3 - -/* some syslogging */ -static void _pam_log(int err, const char *format, ...) -{ - va_list args; - - va_start(args, format); - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -static int _pam_parse(int argc, const char **argv) -{ - int ctrl; - /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= WINBIND_DEBUG_ARG; - else if (!strcasecmp(*argv, "use_authtok")) - ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (!strcasecmp(*argv, "use_first_pass")) - ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "try_first_pass")) - ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "unknown_ok")) - ctrl |= WINBIND_UNKNOWN_OK_ARG; - else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); - } - } - - return ctrl; -} - -/* --- authentication management functions --- */ - -/* Attempt a conversation */ - -static int converse(pam_handle_t *pamh, int nargs, - struct pam_message **message, - struct pam_response **response) -{ - int retval; - struct pam_conv *conv; - - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; - if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, - response, conv->appdata_ptr); - } - - return retval; /* propagate error status */ -} - - -static int _make_remark(pam_handle_t * pamh, int type, const char *text) -{ - int retval = PAM_SUCCESS; - - struct pam_message *pmsg[1], msg[1]; - struct pam_response *resp; - - pmsg[0] = &msg[0]; - msg[0].msg = text; - msg[0].msg_style = type; - - resp = NULL; - retval = converse(pamh, 1, pmsg, &resp); - - if (resp) { - _pam_drop_reply(resp, 1); - } - return retval; -} - -static int pam_winbind_request(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - - /* Fill in request and send down pipe */ - init_request(request, req_type); - - if (write_sock(request, sizeof(*request)) == -1) { - _pam_log(LOG_ERR, "write to socket failed!"); - close_sock(); - return PAM_SERVICE_ERR; - } - - /* Wait for reply */ - if (read_reply(response) == -1) { - _pam_log(LOG_ERR, "read from socket failed!"); - close_sock(); - return PAM_SERVICE_ERR; - } - - /* We are done with the socket - close it and avoid mischeif */ - close_sock(); - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(LOG_ERR, "request failed: %s, PAM error was %d, NT error was %s", - response->data.auth.error_string, - response->data.auth.pam_error, - response->data.auth.nt_status_string); - return response->data.auth.pam_error; - } else { - _pam_log(LOG_ERR, "request failed, but PAM error 0!"); - return PAM_SERVICE_ERR; - } - } - - return PAM_SUCCESS; -} - -static int pam_winbind_request_log(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response, - int ctrl, - const char *user) -{ - int retval; - - retval = pam_winbind_request(req_type, request, response); - - switch (retval) { - case PAM_AUTH_ERR: - /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); - return retval; - case PAM_ACCT_EXPIRED: - /* account expired */ - _pam_log(LOG_WARNING, "user `%s' account expired", user); - return retval; - case PAM_AUTHTOK_EXPIRED: - /* password expired */ - _pam_log(LOG_WARNING, "user `%s' password expired", user); - return retval; - case PAM_NEW_AUTHTOK_REQD: - /* password expired */ - _pam_log(LOG_WARNING, "user `%s' new password required", user); - return retval; - case PAM_USER_UNKNOWN: - /* the user does not exist */ - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", - user); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) { - return PAM_IGNORE; - } - return retval; - case PAM_SUCCESS: - if (req_type == WINBINDD_PAM_AUTH) { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", user); - } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' password changed", user); - } else { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' OK", user); - } - return retval; - default: - /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", - retval, user); - return retval; - } -} - -/* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, int ctrl) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - - strncpy(request.data.auth.user, user, - sizeof(request.data.auth.user)-1); - - strncpy(request.data.auth.pass, pass, - sizeof(request.data.auth.pass)-1); - - - return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); -} - -/* talk to winbindd */ -static int winbind_chauthtok_request(const char *user, const char *oldpass, - const char *newpass, int ctrl) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - - if (request.data.chauthtok.user == NULL) return -2; - - strncpy(request.data.chauthtok.user, user, - sizeof(request.data.chauthtok.user) - 1); - - if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, - sizeof(request.data.chauthtok.oldpass) - 1); - } else { - request.data.chauthtok.oldpass[0] = '\0'; - } - - if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, - sizeof(request.data.chauthtok.newpass) - 1); - } else { - request.data.chauthtok.newpass[0] = '\0'; - } - - return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user); -} - -/* - * Checks if a user has an account - * - * return values: - * 1 = User not found - * 0 = OK - * -1 = System error - */ -static int valid_user(const char *user) -{ - if (getpwnam(user)) return 0; - return 1; -} - -static char *_pam_delete(register char *xx) -{ - _pam_overwrite(xx); - _pam_drop(xx); - return NULL; -} - -/* - * obtain a password from the user - */ - -static int _winbind_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char **pass) -{ - int authtok_flag; - int retval; - const char *item; - char *token; - - /* - * make sure nothing inappropriate gets returned - */ - - *pass = token = NULL; - - /* - * which authentication token are we getting? - */ - - authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; - - /* - * should we obtain the password from a PAM item ? - */ - - if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = pam_get_item(pamh, authtok_flag, (const void **) &item); - if (retval != PAM_SUCCESS) { - /* very strange. */ - _pam_log(LOG_ALERT, - "pam_get_item returned error to unix-read-password" - ); - return retval; - } else if (item != NULL) { /* we have a password! */ - *pass = item; - item = NULL; - return PAM_SUCCESS; - } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ - } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) - && off(WINBIND__OLD_PASSWORD, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; - } - } - /* - * getting here implies we will have to get the password from the - * user directly. - */ - - { - struct pam_message msg[3], *pmsg[3]; - struct pam_response *resp; - int i, replies; - - /* prepare to converse */ - - if (comment != NULL) { - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = comment; - i = 1; - } else { - i = 0; - } - - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt1; - replies = 1; - - if (prompt2 != NULL) { - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt2; - ++replies; - } - /* so call the conversation expecting i responses */ - resp = NULL; - retval = converse(pamh, i, pmsg, &resp); - - if (resp != NULL) { - - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = x_strdup(resp[i - replies].resp); - if (token != NULL) { - if (replies == 2) { - - /* verify that password entered correctly */ - if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh ,PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - _pam_log(LOG_NOTICE - ,"could not recover authentication token"); - } - - } - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - - _pam_drop_reply(resp, i); - - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR : retval; - } - } - - if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, - "unable to obtain a password"); - return retval; - } - /* 'token' is the entered password */ - - /* we store this password as an item */ - - retval = pam_set_item(pamh, authtok_flag, token); - _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS - || (retval = pam_get_item(pamh, authtok_flag - ,(const void **) &item)) - != PAM_SUCCESS) { - - _pam_log(LOG_CRIT, "error manipulating password"); - return retval; - - } - - *pass = item; - item = NULL; /* break link to password */ - - return PAM_SUCCESS; -} - -PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - const char *password; - int retval = PAM_AUTH_ERR; - - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); - return PAM_SERVICE_ERR; - } - - retval = _winbind_read_password(pamh, ctrl, NULL, - "Password: ", NULL, - &password); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrieve user's password"); - return PAM_AUTHTOK_ERR; - } - - if (ctrl & WINBIND_DEBUG_ARG) { - - /* Let's not give too much away in the log file */ - -#ifdef DEBUG_PASSWORD - _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", - username, password); -#else - _pam_log(LOG_INFO, "Verify user `%s'", username); -#endif - } - - /* Now use the username to look up password */ - return winbind_auth_request(username, password, ctrl); -} - -PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - return PAM_SUCCESS; -} - -/* - * Account management. We want to verify that the account exists - * before returning PAM_SUCCESS - */ -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - int retval = PAM_USER_UNKNOWN; - - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); - return PAM_SERVICE_ERR; - } - - /* Verify the username */ - retval = valid_user(username); - switch (retval) { - case -1: - /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; - case 1: - /* the user does not exist */ - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", - username); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) - return PAM_IGNORE; - return PAM_USER_UNKNOWN; - case 0: - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); - return PAM_SUCCESS; - default: - /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; - } - - /* should not be reached */ - return PAM_IGNORE; -} -PAM_EXTERN -int pam_sm_open_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_open_session handler"); - return PAM_SUCCESS; -} -PAM_EXTERN -int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler"); - return PAM_SUCCESS; -} - - - -PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - unsigned int lctrl; - int retval; - unsigned int ctrl = _pam_parse(argc, argv); - - /* <DO NOT free() THESE> */ - const char *user; - char *pass_old, *pass_new; - /* </DO NOT free() THESE> */ - - char *Announce; - - int retry = 0; - - /* - * First get the name of a user - */ - retval = pam_get_user(pamh, &user, "Username: "); - if (retval == PAM_SUCCESS) { - if (user == NULL) { - _pam_log(LOG_ERR, "username was NULL!"); - return PAM_USER_UNKNOWN; - } - if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, "username [%s] obtained", - user); - } else { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, - "password - could not identify user"); - return retval; - } - - /* - * obtain and verify the current password (OLDAUTHTOK) for - * the user. - */ - - if (flags & PAM_PRELIM_CHECK) { - - /* instruct user what is happening */ -#define greeting "Changing password for " - Announce = (char *) malloc(sizeof(greeting) + strlen(user)); - if (Announce == NULL) { - _pam_log(LOG_CRIT, - "password - out of memory"); - return PAM_BUF_ERR; - } - (void) strcpy(Announce, greeting); - (void) strcpy(Announce + sizeof(greeting) - 1, user); -#undef greeting - - lctrl = ctrl | WINBIND__OLD_PASSWORD; - retval = _winbind_read_password(pamh, lctrl - ,Announce - ,"(current) NT password: " - ,NULL - ,(const char **) &pass_old); - free(Announce); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE - ,"password - (old) token not obtained"); - return retval; - } - /* verify that this is the password for this user */ - - retval = winbind_auth_request(user, pass_old, ctrl); - - if (retval != PAM_ACCT_EXPIRED - && retval != PAM_AUTHTOK_EXPIRED - && retval != PAM_NEW_AUTHTOK_REQD - && retval != PAM_SUCCESS) { - pass_old = NULL; - return retval; - } - - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); - pass_old = NULL; - if (retval != PAM_SUCCESS) { - _pam_log(LOG_CRIT, - "failed to set PAM_OLDAUTHTOK"); - } - } else if (flags & PAM_UPDATE_AUTHTOK) { - - /* - * obtain the proposed password - */ - - /* - * get the old token back. - */ - - retval = pam_get_item(pamh, PAM_OLDAUTHTOK - ,(const void **) &pass_old); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE, "user not authenticated"); - return retval; - } - - lctrl = ctrl; - - if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { - ctrl = WINBIND_USE_FIRST_PASS_ARG | lctrl; - } - retry = 0; - retval = PAM_AUTHTOK_ERR; - while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { - /* - * use_authtok is to force the use of a previously entered - * password -- needed for pluggable password strength checking - */ - - retval = _winbind_read_password(pamh, lctrl - ,NULL - ,"Enter new NT password: " - ,"Retype new NT password: " - ,(const char **) &pass_new); - - if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) { - _pam_log(LOG_ALERT - ,"password - new password not obtained"); - } - pass_old = NULL;/* tidy up */ - return retval; - } - - /* - * At this point we know who the user is and what they - * propose as their new password. Verify that the new - * password is acceptable. - */ - - if (pass_new[0] == '\0') {/* "\0" password = NULL */ - pass_new = NULL; - } - } - - /* - * By reaching here we have approved the passwords and must now - * rebuild the password database file. - */ - - retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl); - _pam_overwrite(pass_new); - _pam_overwrite(pass_old); - pass_old = pass_new = NULL; - } else { - retval = PAM_SERVICE_ERR; - } - - return retval; -} - -#ifdef PAM_STATIC - -/* static module data */ - -struct pam_module _pam_winbind_modstruct = { - MODULE_NAME, - pam_sm_authenticate, - pam_sm_setcred, - pam_sm_acct_mgmt, - pam_sm_open_session, - pam_sm_close_session, - pam_sm_chauthtok -}; - -#endif - -/* - * Copyright (c) Andrew Tridgell <tridge@samba.org> 2000 - * Copyright (c) Tim Potter <tpot@samba.org> 2000 - * Copyright (c) Andrew Bartlettt <abartlet@samba.org> 2002 - * Copyright (c) Jan Rêkorajski 1999. - * Copyright (c) Andrew G. Morgan 1996-8. - * Copyright (c) Alex O. Yuriev, 1996. - * Copyright (c) Cristian Gafton 1996. - * Copyright (C) Elliot Lee <sopwith@redhat.com> 1996, Red Hat Software. - * - * 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, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `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 AUTHOR 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. - */ diff --git a/source4/nsswitch/pam_winbind.h b/source4/nsswitch/pam_winbind.h deleted file mode 100644 index fae635d806..0000000000 --- a/source4/nsswitch/pam_winbind.h +++ /dev/null @@ -1,93 +0,0 @@ -/* pam_winbind header file - (Solaris needs some macros from Linux for common PAM code) - - Shirish Kalele 2000 -*/ - -#ifdef HAVE_FEATURES_H -#include <features.h> -#endif - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> - -#include <config.h> - -#define MODULE_NAME "pam_winbind" -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#define PAM_SM_PASSWORD - -#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) - -/* Solaris always uses dynamic pam modules */ -#define PAM_EXTERN extern -#include <security/pam_appl.h> - -#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR -#endif - -#ifdef HAVE_SECURITY_PAM_MODULES_H -#include <security/pam_modules.h> -#endif - -#ifdef HAVE_SECURITY__PAM_MACROS_H -#include <security/_pam_macros.h> -#else -/* Define required macros from (Linux PAM 0.68) security/_pam_macros.h */ -#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ -do { \ - int reply_i; \ - \ - for (reply_i=0; reply_i<replies; ++reply_i) { \ - if (reply[reply_i].resp) { \ - _pam_overwrite(reply[reply_i].resp); \ - free(reply[reply_i].resp); \ - } \ - } \ - if (reply) \ - free(reply); \ -} while (0) - -#define _pam_overwrite(x) \ -do { \ - register char *__xx__; \ - if ((__xx__=(x))) \ - while (*__xx__) \ - *__xx__++ = '\0'; \ -} while (0) - -/* - * Don't just free it, forget it too. - */ - -#define _pam_drop(X) SAFE_FREE(X) - -#define x_strdup(s) ( (s) ? strdup(s):NULL ) -#endif - -#define WINBIND_DEBUG_ARG (1<<0) -#define WINBIND_USE_AUTHTOK_ARG (1<<1) -#define WINBIND_UNKNOWN_OK_ARG (1<<2) -#define WINBIND_TRY_FIRST_PASS_ARG (1<<3) -#define WINBIND_USE_FIRST_PASS_ARG (1<<4) -#define WINBIND__OLD_PASSWORD (1<<5) - -/* - * here is the string to inform the user that the new passwords they - * typed were not the same. - */ - -#define MISTYPED_PASS "Sorry, passwords do not match" - -#define on(x, y) (x & y) -#define off(x, y) (!(x & y)) - -#include "winbind_client.h" diff --git a/source4/nsswitch/wb_client.c b/source4/nsswitch/wb_client.c deleted file mode 100644 index 6f4d895839..0000000000 --- a/source4/nsswitch/wb_client.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client code - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Tridgell 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include "includes.h" -#include "nsswitch/nss.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); - -/* Fetch the list of groups a user is a member of from winbindd. This is - used by winbind_getgroups. */ - -static int wb_getgroups(const char *user, gid_t **groups) -{ - struct winbindd_request request; - struct winbindd_response response; - int result; - - /* Call winbindd */ - - fstrcpy(request.data.username, user); - - ZERO_STRUCT(response); - - result = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (result == NSS_STATUS_SUCCESS) { - - /* Return group list. Don't forget to free the group list - when finished. */ - - *groups = (gid_t *)response.extra_data; - return response.data.num_entries; - } - - return -1; -} - -/* Return a list of groups the user is a member of. This function is - useful for large systems where inverting the group database would be too - time consuming. If size is zero, list is not modified and the total - number of groups for the user is returned. */ - -int winbind_getgroups(const char *user, int size, gid_t *list) -{ - gid_t *groups = NULL; - int result, i; - - /* - * Don't do the lookup if the name has no separator _and_ we are not in - * 'winbind use default domain' mode. - */ - - if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain())) - return -1; - - /* Fetch list of groups */ - - result = wb_getgroups(user, &groups); - - if (size == 0) - goto done; - - if (result > size) { - result = -1; - errno = EINVAL; /* This is what getgroups() does */ - goto done; - } - - /* Copy list of groups across */ - - for (i = 0; i < result; i++) { - list[i] = groups[i]; - } - - done: - SAFE_FREE(groups); - return result; -} diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c deleted file mode 100644 index 89c751a4ef..0000000000 --- a/source4/nsswitch/wb_common.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client common code - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Andrew Bartlett 2002 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include "winbind_client.h" - -/* Global variables. These are effectively the client state information */ - -int winbindd_fd = -1; /* fd for winbindd socket */ - -/* Free a response structure */ - -void free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response) - SAFE_FREE(response->extra_data); -} - -/* Initialise a request structure */ - -void init_request(struct winbindd_request *request, int request_type) -{ - request->length = sizeof(struct winbindd_request); - - request->cmd = (enum winbindd_cmd)request_type; - request->pid = getpid(); - -} - -/* Initialise a response structure */ - -void init_response(struct winbindd_response *response) -{ - /* Initialise return value */ - - response->result = WINBINDD_ERROR; -} - -/* Close established socket */ - -void close_sock(void) -{ - if (winbindd_fd != -1) { - close(winbindd_fd); - winbindd_fd = -1; - } -} - -/* Make sure socket handle isn't stdin, stdout or stderr */ -#define RECURSION_LIMIT 3 - -static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) -{ - int new_fd; - if (fd >= 0 && fd <= 2) { -#ifdef F_DUPFD - if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { - return -1; - } - /* Parinoia */ - if (new_fd < 3) { - close(new_fd); - return -1; - } - close(fd); - return new_fd; -#else - if (limit <= 0) - return -1; - - new_fd = dup(fd); - if (new_fd == -1) - return -1; - - /* use the program stack to hold our list of FDs to close */ - new_fd = make_nonstd_fd_internals(new_fd, limit - 1); - close(fd); - return new_fd; -#endif - } - return fd; -} - -static int make_safe_fd(int fd) -{ - int result, flags; - int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); - if (new_fd == -1) { - close(fd); - return -1; - } - /* Socket should be closed on exec() */ - -#ifdef FD_CLOEXEC - result = flags = fcntl(new_fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl( new_fd, F_SETFD, flags ); - } - if (result < 0) { - close(new_fd); - return -1; - } -#endif - return new_fd; -} - -/* Connect to winbindd socket */ - -int winbind_open_pipe_sock(void) -{ -#ifdef HAVE_UNIXSOCKET - struct sockaddr_un sunaddr; - static pid_t our_pid; - struct stat st; - pstring path; - int fd; - - if (our_pid != getpid()) { - close_sock(); - our_pid = getpid(); - } - - if (winbindd_fd != -1) { - return winbindd_fd; - } - - /* Check permissions on unix socket directory */ - - if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { - return -1; - } - - if (!S_ISDIR(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, "/", sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - ZERO_STRUCT(sunaddr); - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); - - /* If socket file doesn't exist, don't bother trying to connect - with retry. This is an attempt to make the system usable when - the winbindd daemon is not running. */ - - if (lstat(path, &st) == -1) { - return -1; - } - - /* Check permissions on unix socket file */ - - if (!S_ISSOCK(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return -1; - } - - if ((winbindd_fd = make_safe_fd( fd)) == -1) { - return winbindd_fd; - } - - if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, - sizeof(sunaddr)) == -1) { - close_sock(); - return -1; - } - - return winbindd_fd; -#else - return -1; -#endif /* HAVE_UNIXSOCKET */ -} - -/* Write data to winbindd socket */ - -int write_sock(void *buffer, int count) -{ - int result, nwritten; - - /* Open connection to winbind daemon */ - - restart: - - if (winbind_open_pipe_sock() == -1) { - return -1; - } - - /* Write data to socket */ - - nwritten = 0; - - while(nwritten < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - - if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { - close_sock(); - return -1; /* Select error */ - } - - /* Write should be OK if fd not available for reading */ - - if (!FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the write */ - - result = write(winbindd_fd, - (char *)buffer + nwritten, - count - nwritten); - - if ((result == -1) || (result == 0)) { - - /* Write failed */ - - close_sock(); - return -1; - } - - nwritten += result; - - } else { - - /* Pipe has closed on remote end */ - - close_sock(); - goto restart; - } - } - - return nwritten; -} - -/* Read data from winbindd socket */ - -static int read_sock(void *buffer, int count) -{ - int result = 0, nread = 0; - - /* Read data from socket */ - - while(nread < count) { - - result = read(winbindd_fd, (char *)buffer + nread, - count - nread); - - if ((result == -1) || (result == 0)) { - - /* Read failed. I think the only useful thing we - can do here is just return -1 and fail since the - transaction has failed half way through. */ - - close_sock(); - return -1; - } - - nread += result; - } - - return result; -} - -/* Read reply */ - -int read_reply(struct winbindd_response *response) -{ - int result1, result2 = 0; - - if (!response) { - return -1; - } - - /* Read fixed length response */ - - if ((result1 = read_sock(response, sizeof(struct winbindd_response))) - == -1) { - - return -1; - } - - /* We actually send the pointer value of the extra_data field from - the server. This has no meaning in the client's address space - so we clear it out. */ - - response->extra_data = NULL; - - /* Read variable length response */ - - if (response->length > sizeof(struct winbindd_response)) { - int extra_data_len = response->length - - sizeof(struct winbindd_response); - - /* Mallocate memory for extra data */ - - if (!(response->extra_data = malloc(extra_data_len))) { - return -1; - } - - if ((result2 = read_sock(response->extra_data, extra_data_len)) - == -1) { - free_response(response); - return -1; - } - } - - /* Return total amount of data read */ - - return result1 + result2; -} - -/* - * send simple types of requests - */ - -NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) -{ - struct winbindd_request lrequest; - - /* Check for our tricky environment variable */ - - if (getenv(WINBINDD_DONT_ENV)) { - return NSS_STATUS_NOTFOUND; - } - - if (!request) { - ZERO_STRUCT(lrequest); - request = &lrequest; - } - - /* Fill in request and send down pipe */ - - init_request(request, req_type); - - if (write_sock(request, sizeof(*request)) == -1) { - return NSS_STATUS_UNAVAIL; - } - - return NSS_STATUS_SUCCESS; -} - -/* - * Get results from winbindd request - */ - -NSS_STATUS winbindd_get_response(struct winbindd_response *response) -{ - struct winbindd_response lresponse; - - if (!response) { - ZERO_STRUCT(lresponse); - response = &lresponse; - } - - init_response(response); - - /* Wait for reply */ - if (read_reply(response) == -1) { - return NSS_STATUS_UNAVAIL; - } - - /* Throw away extra data if client didn't request it */ - if (response == &lresponse) { - free_response(response); - } - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - return NSS_STATUS_NOTFOUND; - } - - return NSS_STATUS_SUCCESS; -} - -/* Handle simple types of requests */ - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status; - - status = winbindd_send_request(req_type, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - return winbindd_get_response(response); -} diff --git a/source4/nsswitch/wbinfo.c b/source4/nsswitch/wbinfo.c deleted file mode 100644 index 68dc178bcd..0000000000 --- a/source4/nsswitch/wbinfo.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind status program. - - Copyright (C) Tim Potter 2000-2002 - Copyright (C) Andrew Bartlett 2002 - - 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 "winbindd.h" -#include "debug.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern int winbindd_fd; - -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"); - /* HACK: (this module should not call lp_ funtions) */ - return *lp_winbind_separator(); - } - - sep = response.data.info.winbind_separator; - got_sep = True; - - if (!sep) { - d_printf("winbind separator was NULL!\n"); - /* HACK: (this module should not call lp_ funtions) */ - sep = *lp_winbind_separator(); - } - - 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"); - - /* HACK: (this module should not call lp_ funtions) */ - return lp_workgroup(); - } - - fstrcpy(winbind_domain, response.data.domain_name); - - return winbind_domain; - -} - -/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the - form DOMAIN/user into a domain and a user */ - -static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain, - fstring user) -{ - - char *p = strchr(domuser,winbind_separator()); - - if (!p) { - fstrcpy(user, domuser); - fstrcpy(domain, get_winbind_domain()); - return True; - } - - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - strupper(domain); - - return True; -} - -/* List groups a user is a member of */ - -static BOOL wbinfo_get_usergroups(char *user) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - int i; - - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.username, user); - - result = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return False; - - for (i = 0; i < response.data.num_entries; i++) - d_printf("%d\n", (int)((gid_t *)response.extra_data)[i]); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Convert NetBIOS name to IP */ - -static BOOL wbinfo_wins_byname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, name); - - if (winbindd_request(WINBINDD_WINS_BYNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - return False; - } - - /* Display response */ - - printf("%s\n", response.data.winsresp); - - return True; -} - -/* Convert IP to NetBIOS name */ - -static BOOL wbinfo_wins_byip(char *ip) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, ip); - - if (winbindd_request(WINBINDD_WINS_BYIP, &request, &response) != - NSS_STATUS_SUCCESS) { - return False; - } - - /* Display response */ - - printf("%s\n", response.data.winsresp); - - return True; -} - -/* List trusted domains */ - -static BOOL wbinfo_list_domains(void) -{ - struct winbindd_response response; - fstring name; - - ZERO_STRUCT(response); - - /* Send request */ - - if (winbindd_request(WINBINDD_LIST_TRUSTDOM, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - if (response.extra_data) { - const char *extra_data = (char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - } - - return True; -} - - -/* show sequence numbers */ -static BOOL wbinfo_show_sequence(void) -{ - struct winbindd_response response; - - ZERO_STRUCT(response); - - /* Send request */ - - if (winbindd_request(WINBINDD_SHOW_SEQUENCE, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - if (response.extra_data) { - char *extra_data = (char *)response.extra_data; - d_printf("%s", extra_data); - SAFE_FREE(response.extra_data); - } - - return True; -} - -/* Check trust account password */ - -static BOOL wbinfo_check_secret(void) -{ - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(response); - - result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response); - - d_printf("checking the trust secret via RPC calls %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (result != NSS_STATUS_SUCCESS) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Convert uid to sid */ - -static BOOL wbinfo_uid_to_sid(uid_t uid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.uid = uid; - - if (winbindd_request(WINBINDD_UID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return True; -} - -/* Convert gid to sid */ - -static BOOL wbinfo_gid_to_sid(gid_t gid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.gid = gid; - - if (winbindd_request(WINBINDD_GID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return True; -} - -/* Convert sid to uid */ - -static BOOL wbinfo_sid_to_uid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_SID_TO_UID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%d\n", (int)response.data.uid); - - return True; -} - -static BOOL wbinfo_sid_to_gid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_SID_TO_GID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%d\n", (int)response.data.gid); - - return True; -} - -/* Convert sid to string */ - -static BOOL wbinfo_lookupsid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send off request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s%c%s %d\n", response.data.name.dom_name, - winbind_separator(), response.data.name.name, - response.data.name.type); - - return True; -} - -/* Convert string to sid */ - -static BOOL wbinfo_lookupname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - parse_wbinfo_domain_user(name, request.data.name.dom_name, - request.data.name.name); - - if (winbindd_request(WINBINDD_LOOKUPNAME, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s %d\n", response.data.sid.sid, response.data.sid.type); - - return True; -} - -/* Authenticate a user with a plaintext password */ - -static BOOL wbinfo_auth(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, p + 1); - *p = '%'; - } else - fstrcpy(request.data.auth.user, username); - - result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - d_printf("plaintext password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Authenticate a user with a challenge/response */ - -static BOOL wbinfo_auth_crap(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - fstring name_user; - fstring name_domain; - fstring pass; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(pass, p + 1); - } - - parse_wbinfo_domain_user(username, name_domain, name_user); - - fstrcpy(request.data.auth_crap.user, name_user); - - fstrcpy(request.data.auth_crap.domain, name_domain); - - generate_random_buffer(request.data.auth_crap.chal, 8, False); - - SMBencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.lm_resp); - SMBNTencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.nt_resp); - - request.data.auth_crap.lm_resp_len = 24; - request.data.auth_crap.nt_resp_len = 24; - - result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); - - /* Display response */ - - d_printf("challenge/response password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Print domain users */ - -static BOOL print_domain_users(void) -{ - struct winbindd_response response; - const char *extra_data; - fstring name; - - /* Send request to winbind daemon */ - - ZERO_STRUCT(response); - - if (winbindd_request(WINBINDD_LIST_USERS, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Look through extra data */ - - if (!response.extra_data) - return False; - - extra_data = (const char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Print domain groups */ - -static BOOL print_domain_groups(void) -{ - struct winbindd_response response; - const char *extra_data; - fstring name; - - ZERO_STRUCT(response); - - if (winbindd_request(WINBINDD_LIST_GROUPS, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Look through extra data */ - - if (!response.extra_data) - return False; - - extra_data = (const char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Set the authorised user for winbindd access in secrets.tdb */ - -static BOOL wbinfo_set_auth_user(char *username) -{ - char *password; - fstring user, domain; - - /* Separate into user and password */ - - parse_wbinfo_domain_user(username, domain, user); - - password = strchr(user, '%'); - - if (password) { - *password = 0; - password++; - } else - password = ""; - - /* Store or remove DOMAIN\username%password in secrets.tdb */ - - secrets_init(); - - if (user[0]) { - - if (!secrets_store(SECRETS_AUTH_USER, user, - strlen(user) + 1)) { - d_fprintf(stderr, "error storing username\n"); - return False; - } - - /* We always have a domain name added by the - parse_wbinfo_domain_user() function. */ - - if (!secrets_store(SECRETS_AUTH_DOMAIN, domain, - strlen(domain) + 1)) { - d_fprintf(stderr, "error storing domain name\n"); - return False; - } - - } else { - secrets_delete(SECRETS_AUTH_USER); - secrets_delete(SECRETS_AUTH_DOMAIN); - } - - if (password[0]) { - - if (!secrets_store(SECRETS_AUTH_PASSWORD, password, - strlen(password) + 1)) { - d_fprintf(stderr, "error storing password\n"); - return False; - } - - } else - secrets_delete(SECRETS_AUTH_PASSWORD); - - return True; -} - -static void wbinfo_get_auth_user(void) -{ - char *user, *domain, *password; - - /* Lift data from secrets file */ - - secrets_init(); - - user = secrets_fetch(SECRETS_AUTH_USER, NULL); - domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - - if (!user && !domain && !password) { - d_printf("No authorised user configured\n"); - return; - } - - /* Pretty print authorised user info */ - - d_printf("%s%s%s%s%s\n", domain ? domain : "", domain ? "\\" : "", - user, password ? "%" : "", password ? password : ""); - - SAFE_FREE(user); - SAFE_FREE(domain); - SAFE_FREE(password); -} - -static BOOL wbinfo_ping(void) -{ - NSS_STATUS result; - - result = winbindd_request(WINBINDD_PING, NULL, NULL); - - /* Display response */ - - d_printf("'ping' to winbindd %s on fd %d\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd); - - return result == NSS_STATUS_SUCCESS; -} - -/* Main program */ - -enum { - OPT_SET_AUTH_USER = 1000, - OPT_GET_AUTH_USER, - OPT_SEQUENCE -}; - -int main(int argc, char **argv) -{ - int opt; - - poptContext pc; - static char *string_arg; - static int int_arg; - BOOL got_command = False; - int result = 1; - - struct poptOption long_options[] = { - POPT_AUTOHELP - - /* longName, shortName, argInfo, argPtr, value, descrip, - argDesc */ - - { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users"}, - { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups" }, - { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP (WINS)", "NETBIOS-NAME" }, - { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name (WINS)", "IP" }, - { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, - { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, - { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, - { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, - { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, - { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, - { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, - { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, - { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "show sequence numbers of all domains" }, - { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, - { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, - { "set-auth-user", 'A', POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, - { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, - { "ping", 'p', POPT_ARG_NONE, 0, 'p', "'ping' winbindd to see if it is alive" }, - { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version}, - { 0, 0, 0, 0 } - }; - - /* Samba client initialisation */ - - if (!lp_load(dyn_CONFIGFILE, True, False, False)) { - d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n", - dyn_CONFIGFILE, strerror(errno)); - exit(1); - } - - if (!init_names()) - return 1; - - load_interfaces(); - - /* Parse options */ - - pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); - - /* Parse command line options */ - - if (argc == 1) { - poptPrintHelp(pc, stderr, 0); - return 1; - } - - while((opt = poptGetNextOpt(pc)) != -1) { - if (got_command) { - d_fprintf(stderr, "No more than one command may be specified at once.\n"); - exit(1); - } - got_command = True; - } - - poptFreeContext(pc); - - pc = poptGetContext(NULL, argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case 'u': - if (!print_domain_users()) { - d_printf("Error looking up domain users\n"); - goto done; - } - break; - case 'g': - if (!print_domain_groups()) { - d_printf("Error looking up domain groups\n"); - goto done; - } - break; - case 's': - if (!wbinfo_lookupsid(string_arg)) { - d_printf("Could not lookup sid %s\n", string_arg); - goto done; - } - break; - case 'n': - if (!wbinfo_lookupname(string_arg)) { - d_printf("Could not lookup name %s\n", string_arg); - goto done; - } - break; - case 'N': - if (!wbinfo_wins_byname(string_arg)) { - d_printf("Could not lookup WINS by name %s\n", string_arg); - goto done; - } - break; - case 'I': - if (!wbinfo_wins_byip(string_arg)) { - d_printf("Could not lookup WINS by IP %s\n", string_arg); - goto done; - } - break; - case 'U': - if (!wbinfo_uid_to_sid(int_arg)) { - d_printf("Could not convert uid %d to sid\n", int_arg); - goto done; - } - break; - case 'G': - if (!wbinfo_gid_to_sid(int_arg)) { - d_printf("Could not convert gid %d to sid\n", - int_arg); - goto done; - } - break; - case 'S': - if (!wbinfo_sid_to_uid(string_arg)) { - d_printf("Could not convert sid %s to uid\n", - string_arg); - goto done; - } - break; - case 'Y': - if (!wbinfo_sid_to_gid(string_arg)) { - d_printf("Could not convert sid %s to gid\n", - string_arg); - goto done; - } - break; - case 't': - if (!wbinfo_check_secret()) { - d_printf("Could not check secret\n"); - goto done; - } - break; - case 'm': - if (!wbinfo_list_domains()) { - d_printf("Could not list trusted domains\n"); - goto done; - } - break; - case OPT_SEQUENCE: - if (!wbinfo_show_sequence()) { - d_printf("Could not show sequence numbers\n"); - goto done; - } - break; - case 'r': - if (!wbinfo_get_usergroups(string_arg)) { - d_printf("Could not get groups for user %s\n", - string_arg); - goto done; - } - break; - case 'a': { - BOOL got_error = False; - - if (!wbinfo_auth(string_arg)) { - d_printf("Could not authenticate user %s with " - "plaintext password\n", string_arg); - got_error = True; - } - - if (!wbinfo_auth_crap(string_arg)) { - d_printf("Could not authenticate user %s with " - "challenge/response\n", string_arg); - got_error = True; - } - - if (got_error) - goto done; - break; - } - case 'p': { - if (!wbinfo_ping()) { - d_printf("could not ping winbindd!\n"); - goto done; - } - break; - } - case OPT_SET_AUTH_USER: - wbinfo_set_auth_user(string_arg); - break; - case OPT_GET_AUTH_USER: - wbinfo_get_auth_user(); - break; - default: - d_fprintf(stderr, "Invalid option\n"); - poptPrintHelp(pc, stderr, 0); - goto done; - } - } - - result = 0; - - /* Exit code */ - - done: - poptFreeContext(pc); - return result; -} diff --git a/source4/nsswitch/winbind_client.h b/source4/nsswitch/winbind_client.h deleted file mode 100644 index 4de2d57cc7..0000000000 --- a/source4/nsswitch/winbind_client.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "winbind_nss_config.h" -#include "winbindd_nss.h" - -void init_request(struct winbindd_request *req,int rq_type); -NSS_STATUS winbindd_send_request(int req_type, - struct winbindd_request *request); -NSS_STATUS winbindd_get_response(struct winbindd_response *response); -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -int winbind_open_pipe_sock(void); -int write_sock(void *buffer, int count); -int read_reply(struct winbindd_response *response); -void close_sock(void); -void free_response(struct winbindd_response *response); - diff --git a/source4/nsswitch/winbind_nss.c b/source4/nsswitch/winbind_nss.c deleted file mode 100644 index 0b4c0ce1d0..0000000000 --- a/source4/nsswitch/winbind_nss.c +++ /dev/null @@ -1,1341 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Windows NT Domain nsswitch module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include "winbind_client.h" - -#ifdef HAVE_NS_API_H -#undef VOLATILE - -#include <ns_daemon.h> -#endif - -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -/* Prototypes from wb_common.c */ - -extern int winbindd_fd; - - -#ifdef HAVE_NS_API_H -/* IRIX version */ - -static int send_next_request(nsd_file_t *, struct winbindd_request *); -static int do_list(int state, nsd_file_t *rq); - -static nsd_file_t *current_rq = NULL; -static int current_winbind_xid = 0; -static int next_winbind_xid = 0; - -typedef struct winbind_xid { - int xid; - nsd_file_t *rq; - struct winbindd_request *request; - struct winbind_xid *next; -} winbind_xid_t; - -static winbind_xid_t *winbind_xids = (winbind_xid_t *)0; - -static int -winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request) -{ - winbind_xid_t *new; - - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n", - xid, rq, request); - new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t)); - if (!new) { - nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n"); - return NSD_ERROR; - } - - new->xid = xid; - new->rq = rq; - new->request = request; - new->next = winbind_xids; - winbind_xids = new; - - return NSD_CONTINUE; -} - -/* -** This routine will look down the xid list and return the request -** associated with an xid. We remove the record if it is found. -*/ -nsd_file_t * -winbind_xid_lookup(int xid, struct winbindd_request **requestp) -{ - winbind_xid_t **last, *dx; - nsd_file_t *result=0; - - for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid); - last = &dx->next, dx = dx->next); - if (dx) { - *last = dx->next; - result = dx->rq; - *requestp = dx->request; - SAFE_FREE(dx); - } - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n", - xid, result, dx->request); - - return result; -} - -static int -winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n"); - rq = to->t_file; - *rqp = rq; - nsd_timeout_remove(rq); - request = to->t_clientdata; - return(send_next_request(rq, request)); -} - -static void -dequeue_request() -{ - nsd_file_t *rq; - struct winbindd_request *request; - - /* - * Check for queued requests - */ - if (winbind_xids) { - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n", - current_winbind_xid); - rq = winbind_xid_lookup(current_winbind_xid++, &request); - /* cause a timeout on the queued request so we can send it */ - nsd_timeout_new(rq,1,winbind_startnext_timeout,request); - } -} - -static int -do_request(nsd_file_t *rq, struct winbindd_request *request) -{ - if (winbind_xids == NULL) { - /* - * No outstanding requests. - * Send off the request to winbindd - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n"); - return(send_next_request(rq, request)); - } else { - /* - * Just queue it up for now - previous callout or timout - * will start it up - */ - nsd_logprintf(NSD_LOG_MIN, - "lookup (winbind): queue request xid = %d\n", - next_winbind_xid); - return(winbind_xid_new(next_winbind_xid++, rq, request)); - } -} - -static int -winbind_callback(nsd_file_t **rqp, int fd) -{ - struct winbindd_response response; - struct winbindd_pw *pw = &response.data.pw; - struct winbindd_gr *gr = &response.data.gr; - nsd_file_t *rq; - NSS_STATUS status; - fstring result; - char *members; - int i, maxlen; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n"); - - rq = current_rq; - *rqp = rq; - - nsd_timeout_remove(rq); - nsd_callback_remove(fd); - - ZERO_STRUCT(response); - status = winbindd_get_response(&response); - - if (status != NSS_STATUS_SUCCESS) { - /* free any extra data area in response structure */ - free_response(&response); - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) returning not found, status = %d\n", - status); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - maxlen = sizeof(result) - 1; - - switch ((int)rq->f_cmd_data) { - case WINBINDD_WINS_BYNAME: - case WINBINDD_WINS_BYIP: - snprintf(result,maxlen,"%s\n",response.data.winsresp); - break; - case WINBINDD_GETPWUID: - case WINBINDD_GETPWNAM: - snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - break; - case WINBINDD_GETGRNAM: - case WINBINDD_GETGRGID: - if (gr->num_gr_mem && response.extra_data) - members = response.extra_data; - else - members = ""; - snprintf(result,maxlen,"%s:%s:%d:%s\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, members); - break; - case WINBINDD_SETGRENT: - case WINBINDD_SETPWENT: - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - SETPWENT/SETGRENT\n"); - free_response(&response); - return(do_list(1,rq)); - case WINBINDD_GETGRENT: - case WINBINDD_GETGRLST: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) - %d GETGRENT responses\n", - response.data.num_entries); - if (response.data.num_entries) { - gr = (struct winbindd_gr *)response.extra_data; - if (! gr ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - free_response(&response); - return NSD_ERROR; - } - members = (char *)response.extra_data + - (response.data.num_entries * sizeof(struct winbindd_gr)); - for (i = 0; i < response.data.num_entries; i++) { - snprintf(result,maxlen,"%s:%s:%d:%s\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, - &members[gr->gr_mem_ofs]); - nsd_logprintf(NSD_LOG_MIN, " GETGRENT %s\n",result); - nsd_append_element(rq,NS_SUCCESS,result,strlen(result)); - gr++; - } - } - i = response.data.num_entries; - free_response(&response); - if (i < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - case WINBINDD_GETPWENT: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) - %d GETPWENT responses\n", - response.data.num_entries); - if (response.data.num_entries) { - pw = (struct winbindd_pw *)response.extra_data; - if (! pw ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - free_response(&response); - return NSD_ERROR; - } - for (i = 0; i < response.data.num_entries; i++) { - snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result); - nsd_append_element(rq,NS_SUCCESS,result,strlen(result)); - pw++; - } - } - i = response.data.num_entries; - free_response(&response); - if (i < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - case WINBINDD_ENDGRENT: - case WINBINDD_ENDPWENT: - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - ENDPWENT/ENDGRENT\n"); - nsd_append_element(rq,NS_SUCCESS,"\n",1); - free_response(&response); - return NSD_NEXT; - default: - free_response(&response); - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n"); - return NSD_NEXT; - } - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) %s\n", result); - /* free any extra data area in response structure */ - free_response(&response); - nsd_set_result(rq,NS_SUCCESS,result,strlen(result),VOLATILE); - return NSD_OK; -} - -static int -winbind_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n"); - - rq = to->t_file; - *rqp = rq; - - /* Remove the callback and timeout */ - nsd_callback_remove(winbindd_fd); - nsd_timeout_remove(rq); - - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -static int -send_next_request(nsd_file_t *rq, struct winbindd_request *request) -{ - NSS_STATUS status; - long timeout; - - timeout = 1000; - - nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n", - rq->f_cmd_data, timeout); - status = winbindd_send_request((int)rq->f_cmd_data,request); - SAFE_FREE(request); - - if (status != NSS_STATUS_SUCCESS) { - nsd_logprintf(NSD_LOG_MIN, - "send_next_request (winbind) error status = %d\n",status); - rq->f_status = status; - return NSD_NEXT; - } - - current_rq = rq; - - /* - * Set up callback and timeouts - */ - nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",winbindd_fd); - nsd_callback_new(winbindd_fd,winbind_callback,NSD_READ); - nsd_timeout_new(rq,timeout,winbind_timeout,(void *)0); - return NSD_CONTINUE; -} - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n"); - return(NSD_OK); -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! map || ! key) { - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map); - - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "lookup (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byuid") == 0) { - request->data.uid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETPWUID; - } else if (strcasecmp(map,"passwd.byname") == 0) { - strncpy(request->data.username, key, - sizeof(request->data.username) - 1); - request->data.username[sizeof(request->data.username) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETPWNAM; - } else if (strcasecmp(map,"group.byname") == 0) { - strncpy(request->data.groupname, key, - sizeof(request->data.groupname) - 1); - request->data.groupname[sizeof(request->data.groupname) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETGRNAM; - } else if (strcasecmp(map,"group.bygid") == 0) { - request->data.gid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETGRGID; - } else if (strcasecmp(map,"hosts.byname") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME; - } else if (strcasecmp(map,"hosts.byaddr") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP; - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -int list(nsd_file_t *rq) -{ - char *map; - - nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map ) { - nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map); - - return (do_list(0,rq)); -} - -static int -do_list(int state, nsd_file_t *rq) -{ - char *map; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state); - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "do_list (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETPWENT; - break; - case 1: - request->data.num_entries = MAX_GETPWENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETPWENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDPWENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else if (strcasecmp(map,"group.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETGRENT; - break; - case 1: - request->data.num_entries = MAX_GETGRENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETGRENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDGRENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -#else - -/* Allocate some space from the nss static buffer. The buffer and buflen - are the pointers passed in by the C library to the _nss_ntdom_* - functions. */ - -static char *get_static(char **buffer, int *buflen, int len) -{ - char *result; - - /* Error check. We return false if things aren't set up right, or - there isn't enough buffer space left. */ - - if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { - return NULL; - } - - /* Return an index into the static buffer */ - - result = *buffer; - *buffer += len; - *buflen -= len; - - return result; -} - -/* I've copied the strtok() replacement function next_token() from - lib/util_str.c as I really don't want to have to link in any other - objects if I can possibly avoid it. */ - -BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize) -{ - char *s; - BOOL quoted; - size_t len=1; - - if (!ptr) return(False); - - s = *ptr; - - /* default to simple separators */ - if (!sep) sep = " \t\n\r"; - - /* find the first non sep char */ - while (*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (! *s) return(False); - - /* copy over the token */ - for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { - if (*s == '\"') { - quoted = !quoted; - } else { - len++; - *buff++ = *s; - } - } - - *ptr = (*s) ? s+1 : s; - *buff = 0; - - return(True); -} - - -/* Fill a pwent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_pwent(struct passwd *result, - struct winbindd_pw *pw, - char **buffer, size_t *buflen) -{ - /* User name */ - - if ((result->pw_name = - get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_name, pw->pw_name); - - /* Password */ - - if ((result->pw_passwd = - get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_passwd, pw->pw_passwd); - - /* [ug]id */ - - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; - - /* GECOS */ - - if ((result->pw_gecos = - get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_gecos, pw->pw_gecos); - - /* Home directory */ - - if ((result->pw_dir = - get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_dir, pw->pw_dir); - - /* Logon shell */ - - if ((result->pw_shell = - get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_shell, pw->pw_shell); - - /* The struct passwd for Solaris has some extra fields which must - be initialised or nscd crashes. */ - -#if HAVE_PASSWD_PW_COMMENT - result->pw_comment = ""; -#endif - -#if HAVE_PASSWD_PW_AGE - result->pw_age = ""; -#endif - - return NSS_STATUS_SUCCESS; -} - -/* Fill a grent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, - char *gr_mem, char **buffer, size_t *buflen) -{ - fstring name; - int i; - char *tst; - - /* Group name */ - - if ((result->gr_name = - get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_name, gr->gr_name); - - /* Password */ - - if ((result->gr_passwd = - get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_passwd, gr->gr_passwd); - - /* gid */ - - result->gr_gid = gr->gr_gid; - - /* Group membership */ - - if ((gr->num_gr_mem < 0) || !gr_mem) { - gr->num_gr_mem = 0; - } - - /* this next value is a pointer to a pointer so let's align it */ - - /* Calculate number of extra bytes needed to align on pointer size boundry */ - if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * - sizeof(char *)+i))) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - result->gr_mem = (char **)(tst + i); - - if (gr->num_gr_mem == 0) { - - /* Group is empty */ - - *(result->gr_mem) = NULL; - return NSS_STATUS_SUCCESS; - } - - /* Start looking at extra data */ - - i = 0; - - while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) { - - /* Allocate space for member */ - - if (((result->gr_mem)[i] = - get_static(buffer, buflen, strlen(name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy((result->gr_mem)[i], name); - i++; - } - - /* Terminate list */ - - (result->gr_mem)[i] = NULL; - - return NSS_STATUS_SUCCESS; -} - -/* - * NSS user functions - */ - -static struct winbindd_response getpwent_response; - -static int ndx_pw_cache; /* Current index into pwd cache */ -static int num_pw_cache; /* Current size of pwd cache */ - -/* Rewind "file pointer" to start of ntdom password database */ - -NSS_STATUS -_nss_winbind_setpwent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - - return winbindd_request(WINBINDD_SETPWENT, NULL, NULL); -} - -/* Close ntdom password database "file pointer" */ - -NSS_STATUS -_nss_winbind_endpwent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - - return winbindd_request(WINBINDD_ENDPWENT, NULL, NULL); -} - -/* Fetch the next password entry from ntdom password database */ - -NSS_STATUS -_nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - static int called_again; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_pw_cache < num_pw_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_pw_cache > 0) { - free_response(&getpwent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getpwent_response); - - request.data.num_entries = MAX_GETPWENT_USERS; - - ret = winbindd_request(WINBINDD_GETPWENT, &request, - &getpwent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_pw *pw_cache; - - /* Fill cache */ - - ndx_pw_cache = 0; - num_pw_cache = getpwent_response.data.num_entries; - - /* Return a result */ - - return_result: - - pw_cache = getpwent_response.extra_data; - - /* Check data is valid */ - - if (pw_cache == NULL) { - return NSS_STATUS_NOTFOUND; - } - - ret = fill_pwent(result, &pw_cache[ndx_pw_cache], - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; - *errnop = errno = ERANGE; - return ret; - } - - *errnop = errno = 0; - called_again = False; - ndx_pw_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_pw_cache == num_pw_cache) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - } - - return ret; -} - -/* Return passwd struct from uid */ - -NSS_STATUS -_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response=0; - - /* If our static buffer needs to be expanded we are called again */ - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = errno = 0; - } - - free_response(&response); - return ret; -} - -/* Return passwd struct from username */ - -NSS_STATUS -_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.username, name, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; - - ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = errno = 0; - } - - free_response(&response); - return ret; -} - -/* - * NSS group functions - */ - -static struct winbindd_response getgrent_response; - -static int ndx_gr_cache; /* Current index into grp cache */ -static int num_gr_cache; /* Current size of grp cache */ - -/* Rewind "file pointer" to start of ntdom group database */ - -NSS_STATUS -_nss_winbind_setgrent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - - return winbindd_request(WINBINDD_SETGRENT, NULL, NULL); -} - -/* Close "file pointer" for ntdom group database */ - -NSS_STATUS -_nss_winbind_endgrent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - - return winbindd_request(WINBINDD_ENDGRENT, NULL, NULL); -} - -/* Get next entry from ntdom group database */ - -static NSS_STATUS -winbind_getgrent(enum winbindd_cmd cmd, - struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_request request; - static int called_again; - - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_gr_cache < num_gr_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_gr_cache > 0) { - free_response(&getgrent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getgrent_response); - - request.data.num_entries = MAX_GETGRENT_USERS; - - ret = winbindd_request(cmd, &request, - &getgrent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_gr *gr_cache; - int mem_ofs; - - /* Fill cache */ - - ndx_gr_cache = 0; - num_gr_cache = getgrent_response.data.num_entries; - - /* Return a result */ - - return_result: - - gr_cache = getgrent_response.extra_data; - - /* Check data is valid */ - - if (gr_cache == NULL) { - return NSS_STATUS_NOTFOUND; - } - - /* Fill group membership. The offset into the extra data - for the group membership is the reported offset plus the - size of all the winbindd_gr records returned. */ - - mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + - num_gr_cache * sizeof(struct winbindd_gr); - - ret = fill_grent(result, &gr_cache[ndx_gr_cache], - ((char *)getgrent_response.extra_data)+mem_ofs, - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; - *errnop = errno = ERANGE; - return ret; - } - - *errnop = 0; - called_again = False; - ndx_gr_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_gr_cache == num_gr_cache) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - } - - return ret; -} - - -NSS_STATUS -_nss_winbind_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); -} - -NSS_STATUS -_nss_winbind_getgrlst_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); -} - -/* Return group struct from group name */ - -NSS_STATUS -_nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.groupname, name, - sizeof(request.data.groupname)); - request.data.groupname - [sizeof(request.data.groupname) - 1] = '\0'; - - ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_grent(result, &response.data.gr, - response.extra_data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - response.extra_data, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = 0; - } - - free_response(&response); - return ret; -} - -/* Return group struct from gid */ - -NSS_STATUS -_nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - ret = winbindd_request(WINBINDD_GETGRGID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - - ret = fill_grent(result, &response.data.gr, - response.extra_data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - response.extra_data, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = 0; - } - - free_response(&response); - return ret; -} - -/* Initialise supplementary groups */ - -NSS_STATUS -_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, long int limit, - int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int i; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), - user, group); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.username, user, - sizeof(request.data.username) - 1); - - ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - int num_gids = response.data.num_entries; - gid_t *gid_list = (gid_t *)response.extra_data; - - /* Copy group list to client */ - - for (i = 0; i < num_gids; i++) { - - /* Skip primary group */ - - if (gid_list[i] == group) continue; - - /* Add to buffer */ - - if (*start == *size && limit <= 0) { - (*groups) = realloc( - (*groups), (2 * (*size) + 1) * sizeof(**groups)); - if (! *groups) goto done; - *size = 2 * (*size) + 1; - } - - if (*start == *size) goto done; - - (*groups)[*start] = gid_list[i]; - *start += 1; - - /* Filled buffer? */ - - if (*start == limit) goto done; - } - } - - /* Back to your regularly scheduled programming */ - - done: - return ret; -} - -#endif diff --git a/source4/nsswitch/winbind_nss_config.h b/source4/nsswitch/winbind_nss_config.h deleted file mode 100644 index 2faaa30d1b..0000000000 --- a/source4/nsswitch/winbind_nss_config.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifndef _WINBIND_NSS_CONFIG_H -#define _WINBIND_NSS_CONFIG_H - -/* Include header files from data in config.h file */ - -#ifndef NO_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif - -#ifdef HAVE_UNIXSOCKET -#include <sys/un.h> -#endif - -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif - -#ifdef HAVE_GRP_H -#include <grp.h> -#endif - -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#else -#ifdef HAVE_SYS_FCNTL_H -#include <sys/fcntl.h> -#endif -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <pwd.h> -#include "nsswitch/nss.h" - -/* Declarations for functions in winbind_nss.c - needed in winbind_nss_solaris.c (solaris wrapper to nss) */ - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result, - char* buffer, size_t buflen, int* errnop); - -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop); - -/* I'm trying really hard not to include anything from smb.h with the - result of some silly looking redeclaration of structures. */ - -#ifndef _PSTRING -#define _PSTRING -#define PSTRING_LEN 1024 -#define FSTRING_LEN 256 -typedef char pstring[PSTRING_LEN]; -typedef char fstring[FSTRING_LEN]; -#endif - -#ifndef _BOOL -#define _BOOL /* So we don't typedef BOOL again in vfs.h */ -#define False (0) -#define True (1) -#define Auto (2) -typedef int BOOL; -#endif - -#if !defined(uint32) -#if (SIZEOF_INT == 4) -#define uint32 unsigned int -#elif (SIZEOF_LONG == 4) -#define uint32 unsigned long -#elif (SIZEOF_SHORT == 4) -#define uint32 unsigned short -#endif -#endif - -#if !defined(uint16) -#if (SIZEOF_SHORT == 4) -#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; -#else /* SIZEOF_SHORT != 4 */ -#define uint16 unsigned short -#endif /* SIZEOF_SHORT != 4 */ -#endif - -#ifndef uint8 -#define uint8 unsigned char -#endif - -/* zero a structure */ -#ifndef ZERO_STRUCT -#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) -#endif - -/* zero a structure given a pointer to the structure */ -#ifndef ZERO_STRUCTP -#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } -#endif - -/* Some systems (SCO) treat UNIX domain sockets as FIFOs */ - -#ifndef S_IFSOCK -#define S_IFSOCK S_IFIFO -#endif - -#ifndef S_ISSOCK -#define S_ISSOCK(mode) ((mode & S_IFSOCK) == S_IFSOCK) -#endif - -#endif diff --git a/source4/nsswitch/winbind_nss_solaris.c b/source4/nsswitch/winbind_nss_solaris.c deleted file mode 100644 index f3bd05b77a..0000000000 --- a/source4/nsswitch/winbind_nss_solaris.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - Solaris NSS wrapper for winbind - - Shirish Kalele 2000 - - Based on Luke Howard's ldap_nss module for Solaris - */ - -/* - Copyright (C) 1997-2003 Luke Howard. - This file is part of the nss_ldap library. - - The nss_ldap library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The nss_ldap library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the nss_ldap library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include <stdlib.h> -#include <sys/types.h> -#include <sys/param.h> -#include <string.h> -#include <pwd.h> -#include "includes.h" -#include <syslog.h> -#if !defined(HPUX) -#include <sys/syslog.h> -#endif /*hpux*/ -#include "winbind_nss_config.h" - -#if defined(HAVE_NSS_COMMON_H) || defined(HPUX) - -#undef NSS_DEBUG - -#ifdef NSS_DEBUG -#define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str); -#else -#define NSS_DEBUG(str) ; -#endif - -#define NSS_ARGS(args) ((nss_XbyY_args_t *)args) - -#define make_pwent_str(dest, src) \ -{ \ - if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \ - { \ - *errnop = ERANGE; \ - NSS_DEBUG("ERANGE error"); \ - return NSS_STATUS_TRYAGAIN; \ - } \ - strcpy(dest, src); \ -} - -static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setpwent_solwrap"); - return _nss_winbind_setpwent(); -} - -static NSS_STATUS -_nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endpwent_solwrap"); - return _nss_winbind_endpwent(); -} - -static NSS_STATUS -_nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getpwent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n", - result->pw_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret); - NSS_DEBUG(logmsg); - } - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwnam_solwrap"); - - ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwuid_solwrap"); - ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_passwd_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t passwd_ops[] = -{ - _nss_winbind_passwd_destr, - _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */ - _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */ - _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */ - _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */ - _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */ -}; - -nss_backend_t* -_nss_winbind_passwd_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t *be; - - if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) ) - return NULL; - - be->ops = passwd_ops; - be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind passwd backend"); - return be; -} - -/***************************************************************** - GROUP database backend - *****************************************************************/ - -static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setgrent_solwrap"); - return _nss_winbind_setgrent(); -} - -static NSS_STATUS -_nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endgrent_solwrap"); - return _nss_winbind_endgrent(); -} - -static NSS_STATUS -_nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getgrent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret); - NSS_DEBUG(logmsg); - } - - return ret; - -} - -static NSS_STATUS -_nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrnam_solwrap"); - ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrgid_solwrap"); - ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_getgroupsbymember"); - return NSS_STATUS_NOTFOUND; -} - -static NSS_STATUS -_nss_winbind_group_destr (nss_backend_t* be, void* args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_group_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t group_ops[] = -{ - _nss_winbind_group_destr, - _nss_winbind_endgrent_solwrap, - _nss_winbind_setgrent_solwrap, - _nss_winbind_getgrent_solwrap, - _nss_winbind_getgrnam_solwrap, - _nss_winbind_getgrgid_solwrap, - _nss_winbind_getgroupsbymember_solwrap -}; - -nss_backend_t* -_nss_winbind_group_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t* be; - - if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) ) - return NULL; - - be->ops = group_ops; - be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind group backend"); - return be; -} - -#endif /* SUN_NSS */ - - diff --git a/source4/nsswitch/winbindd.c b/source4/nsswitch/winbindd.c deleted file mode 100644 index 23394f5e8c..0000000000 --- a/source4/nsswitch/winbindd.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) by Tim Potter 2000-2002 - Copyright (C) Andrew Tridgell 2002 - - 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 "winbindd.h" - -BOOL opt_nocache = False; -BOOL opt_dual_daemon = False; - -/* Reload configuration */ - -static BOOL reload_services_file(BOOL test) -{ - BOOL ret; - pstring logfile; - - if (lp_loaded()) { - pstring fname; - - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); - test = False; - } - } - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - reopen_logs(); - ret = lp_load(dyn_CONFIGFILE,False,False,True); - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - reopen_logs(); - load_interfaces(); - - return(ret); -} - -/******************************************************************* - Print out all talloc memory info. -********************************************************************/ - -void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len) -{ - TALLOC_CTX *ctx = talloc_init("info context"); - char *info = NULL; - - if (!ctx) - return; - - info = talloc_describe_all(ctx); - if (info) - DEBUG(10,(info)); - message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1: 0, True); - talloc_destroy(ctx); -} - -#if DUMP_CORE - -/**************************************************************************** ** - Prepare to dump a core file - carefully! - **************************************************************************** */ - -static BOOL dump_core(void) -{ - char *p; - pstring dname; - pstrcpy( dname, lp_logfile() ); - if ((p=strrchr(dname,'/'))) - *p=0; - pstrcat( dname, "/corefiles" ); - mkdir( dname, 0700 ); - sys_chown( dname, getuid(), getgid() ); - chmod( dname, 0700 ); - if ( chdir(dname) ) - return( False ); - umask( ~(0700) ); - -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit( RLIMIT_CORE, &rlp ); - rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur ); - setrlimit( RLIMIT_CORE, &rlp ); - getrlimit( RLIMIT_CORE, &rlp ); - DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) ); - } -#endif -#endif - - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return( True ); -} /* dump_core */ -#endif - -/**************************************************************************** ** - Handle a fault.. - **************************************************************************** */ - -static void fault_quit(void) -{ -#if DUMP_CORE - dump_core(); -#endif -} - -static void winbindd_status(void) -{ - struct winbindd_cli_state *tmp; - - DEBUG(0, ("winbindd status:\n")); - - /* Print client state information */ - - DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients())); - - if (DEBUGLEVEL >= 2 && winbindd_num_clients()) { - DEBUG(2, ("\tclient list:\n")); - for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) { - DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n", - tmp->pid, tmp->sock, tmp->read_buf_len, - tmp->write_buf_len)); - } - } -} - -/* Print winbindd status to log file */ - -static void print_winbindd_status(void) -{ - winbindd_status(); - winbindd_idmap_status(); - winbindd_cm_status(); -} - -/* Flush client cache */ - -static void flush_caches(void) -{ - /* Clear cached user and group enumation info */ - wcache_flush_cache(); -} - -/* Handle the signal by unlinking socket and exiting */ - -static void terminate(void) -{ - pstring path; - - winbindd_idmap_close(); - - /* Remove socket file */ - snprintf(path, sizeof(path), "%s/%s", - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); - unlink(path); - exit(0); -} - -static BOOL do_sigterm; - -static void termination_handler(int signum) -{ - do_sigterm = True; - sys_select_signal(); -} - -static BOOL do_sigusr2; - -static void sigusr2_handler(int signum) -{ - do_sigusr2 = True; - sys_select_signal(); -} - -static BOOL do_sighup; - -static void sighup_handler(int signum) -{ - do_sighup = True; - sys_select_signal(); -} - -struct dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -static struct dispatch_table dispatch_table[] = { - - /* User functions */ - - { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" }, - { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" }, - - { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" }, - { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" }, - { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, - - { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, - - /* Group functions */ - - { WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" }, - { WINBINDD_GETGRGID, winbindd_getgrgid, "GETGRGID" }, - { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" }, - { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" }, - { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" }, - { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" }, - - /* PAM auth functions */ - - { WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" }, - { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" }, - { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" }, - - /* Enumeration functions */ - - { WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" }, - { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" }, - { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains, "LIST_TRUSTDOM" }, - { WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" }, - - /* SID related functions */ - - { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" }, - { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, - - /* Lookup related functions */ - - { WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" }, - { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" }, - { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" }, - { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" }, - - /* Miscellaneous */ - - { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_PING, winbindd_ping, "PING" }, - { WINBINDD_INFO, winbindd_info, "INFO" }, - { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" }, - { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" }, - { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" }, - - /* WINS functions */ - - { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" }, - { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" }, - - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } -}; - -static void process_request(struct winbindd_cli_state *state) -{ - struct dispatch_table *table = dispatch_table; - - /* Free response data - we may be interrupted and receive another - command before being able to send this data off. */ - - SAFE_FREE(state->response.extra_data); - - ZERO_STRUCT(state->response); - - state->response.result = WINBINDD_ERROR; - state->response.length = sizeof(struct winbindd_response); - - /* Process command */ - - for (table = dispatch_table; table->fn; table++) { - if (state->request.cmd == table->cmd) { - DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name )); - state->response.result = table->fn(state); - break; - } - } - - if (!table->fn) - DEBUG(10,("process_request: unknown request fn number %d\n", (int)state->request.cmd )); - - /* In case extra data pointer is NULL */ - - if (!state->response.extra_data) - state->response.length = sizeof(struct winbindd_response); -} - -/* Process a new connection by adding it to the client connection list */ - -static void new_connection(int listen_sock) -{ - struct sockaddr_un sunaddr; - struct winbindd_cli_state *state; - socklen_t len; - int sock; - - /* Accept connection */ - - len = sizeof(sunaddr); - - do { - sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len); - } while (sock == -1 && errno == EINTR); - - if (sock == -1) - return; - - DEBUG(6,("accepted socket %d\n", sock)); - - /* Create new connection structure */ - - if ((state = (struct winbindd_cli_state *) - malloc(sizeof(*state))) == NULL) - return; - - ZERO_STRUCTP(state); - state->sock = sock; - - state->last_access = time(NULL); - - /* Add to connection list */ - - winbindd_add_client(state); -} - -/* Remove a client connection from client connection list */ - -static void remove_client(struct winbindd_cli_state *state) -{ - /* It's a dead client - hold a funeral */ - - if (state != NULL) { - - /* Close socket */ - - close(state->sock); - - /* Free any getent state */ - - free_getent_state(state->getpwent_state); - free_getent_state(state->getgrent_state); - - /* We may have some extra data that was not freed if the - client was killed unexpectedly */ - - SAFE_FREE(state->response.extra_data); - - /* Remove from list and free */ - - winbindd_remove_client(state); - SAFE_FREE(state); - } -} - - -/* Shutdown client connection which has been idle for the longest time */ - -static BOOL remove_idle_client(void) -{ - struct winbindd_cli_state *state, *remove_state = NULL; - time_t last_access = 0; - int nidle = 0; - - for (state = winbindd_client_list(); state; state = state->next) { - if (state->read_buf_len == 0 && state->write_buf_len == 0 && - !state->getpwent_state && !state->getgrent_state) { - nidle++; - if (!last_access || state->last_access < last_access) { - last_access = state->last_access; - remove_state = state; - } - } - } - - if (remove_state) { - DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n", - nidle, remove_state->sock, (unsigned int)remove_state->pid)); - remove_client(remove_state); - return True; - } - - return False; -} - -/* Process a complete received packet from a client */ - -void winbind_process_packet(struct winbindd_cli_state *state) -{ - /* Process request */ - - /* Ensure null termination of entire request */ - state->request.null_term = '\0'; - - state->pid = state->request.pid; - - process_request(state); - - /* Update client state */ - - state->read_buf_len = 0; - state->write_buf_len = sizeof(struct winbindd_response); - - /* we might need to send it to the dual daemon */ - if (opt_dual_daemon) { - dual_send_request(state); - } -} - -/* Read some data from a client connection */ - -void winbind_client_read(struct winbindd_cli_state *state) -{ - int n; - - /* Read data */ - - n = sys_read(state->sock, state->read_buf_len + - (char *)&state->request, - sizeof(state->request) - state->read_buf_len); - - DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len )); - - /* Read failed, kill client */ - - if (n == -1 || n == 0) { - DEBUG(5,("read failed on sock %d, pid %d: %s\n", - state->sock, state->pid, - (n == -1) ? strerror(errno) : "EOF")); - - state->finished = True; - return; - } - - /* Update client state */ - - state->read_buf_len += n; - state->last_access = time(NULL); -} - -/* Write some data to a client connection */ - -static void client_write(struct winbindd_cli_state *state) -{ - char *data; - int num_written; - - /* Write some data */ - - if (!state->write_extra_data) { - - /* Write response structure */ - - data = (char *)&state->response + sizeof(state->response) - - state->write_buf_len; - - } else { - - /* Write extra data */ - - data = (char *)state->response.extra_data + - state->response.length - - sizeof(struct winbindd_response) - - state->write_buf_len; - } - - num_written = sys_write(state->sock, data, state->write_buf_len); - - DEBUG(10,("client_write: wrote %d bytes.\n", num_written )); - - /* Write failed, kill cilent */ - - if (num_written == -1 || num_written == 0) { - - DEBUG(3,("write failed on sock %d, pid %d: %s\n", - state->sock, state->pid, - (num_written == -1) ? strerror(errno) : "EOF")); - - state->finished = True; - - SAFE_FREE(state->response.extra_data); - - return; - } - - /* Update client state */ - - state->write_buf_len -= num_written; - state->last_access = time(NULL); - - /* Have we written all data? */ - - if (state->write_buf_len == 0) { - - /* Take care of extra data */ - - if (state->write_extra_data) { - - SAFE_FREE(state->response.extra_data); - - state->write_extra_data = False; - - DEBUG(10,("client_write: client_write: complete response written.\n")); - - } else if (state->response.length > - sizeof(struct winbindd_response)) { - - /* Start writing extra data */ - - state->write_buf_len = - state->response.length - - sizeof(struct winbindd_response); - - DEBUG(10,("client_write: need to write %d extra data bytes.\n", (int)state->write_buf_len)); - - state->write_extra_data = True; - } - } -} - -/* Process incoming clients on listen_sock. We use a tricky non-blocking, - non-forking, non-threaded model which allows us to handle many - simultaneous connections while remaining impervious to many denial of - service attacks. */ - -static void process_loop(void) -{ - /* We'll be doing this a lot */ - - while (1) { - struct winbindd_cli_state *state; - fd_set r_fds, w_fds; - int maxfd, listen_sock, selret; - struct timeval timeout; - - /* Handle messages */ - - message_dispatch(); - - /* rescan the trusted domains list. This must be done - regularly to cope with transitive trusts */ - rescan_trusted_domains(False); - - /* Free up temporary memory */ - - lp_talloc_free(); - main_loop_talloc_free(); - - /* Initialise fd lists for select() */ - - listen_sock = open_winbindd_socket(); - - if (listen_sock == -1) { - perror("open_winbind_socket"); - exit(1); - } - - maxfd = listen_sock; - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - FD_SET(listen_sock, &r_fds); - - timeout.tv_sec = WINBINDD_ESTABLISH_LOOP; - timeout.tv_usec = 0; - - if (opt_dual_daemon) { - maxfd = dual_select_setup(&w_fds, maxfd); - } - - /* Set up client readers and writers */ - - state = winbindd_client_list(); - - while (state) { - - /* Dispose of client connection if it is marked as - finished */ - - if (state->finished) { - struct winbindd_cli_state *next = state->next; - - remove_client(state); - state = next; - continue; - } - - /* Select requires we know the highest fd used */ - - if (state->sock > maxfd) - maxfd = state->sock; - - /* Add fd for reading */ - - if (state->read_buf_len != sizeof(state->request)) - FD_SET(state->sock, &r_fds); - - /* Add fd for writing */ - - if (state->write_buf_len) - FD_SET(state->sock, &w_fds); - - state = state->next; - } - - /* Call select */ - - selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); - - if (selret == 0) - continue; - - if ((selret == -1 && errno != EINTR) || selret == 0) { - - /* Select error, something is badly wrong */ - - perror("select"); - exit(1); - } - - /* Create a new connection if listen_sock readable */ - - if (selret > 0) { - - if (opt_dual_daemon) { - dual_select(&w_fds); - } - - if (FD_ISSET(listen_sock, &r_fds)) { - while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { - DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - if (!remove_idle_client()) { - DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - break; - } - } - new_connection(listen_sock); - } - - /* Process activity on client connections */ - - for (state = winbindd_client_list(); state; - state = state->next) { - - /* Data available for reading */ - - if (FD_ISSET(state->sock, &r_fds)) { - - /* Read data */ - - winbind_client_read(state); - - /* - * If we have the start of a - * packet, then check the - * length field to make sure - * the client's not talking - * Mock Swedish. - */ - - if (state->read_buf_len >= sizeof(uint32) - && *(uint32 *) &state->request != sizeof(state->request)) { - DEBUG(0,("process_loop: Invalid request size from pid %d: %d bytes sent, should be %d\n", - state->request.pid, *(uint32 *) &state->request, sizeof(state->request))); - - remove_client(state); - break; - } - - /* A request packet might be - complete */ - - if (state->read_buf_len == - sizeof(state->request)) { - winbind_process_packet(state); - } - } - - /* Data available for writing */ - - if (FD_ISSET(state->sock, &w_fds)) - client_write(state); - } - } - -#if 0 - winbindd_check_cache_size(time(NULL)); -#endif - - /* Check signal handling things */ - - if (do_sigterm) - terminate(); - - if (do_sighup) { - - DEBUG(3, ("got SIGHUP\n")); - - /* Flush various caches */ - - flush_caches(); - reload_services_file(True); - do_sighup = False; - } - - if (do_sigusr2) { - print_winbindd_status(); - do_sigusr2 = False; - } - } -} - - -/* - these are split out from the main winbindd for use by the background daemon - */ -BOOL winbind_setup_common(void) -{ - load_interfaces(); - - if (!secrets_init()) { - - DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); - return False; - } - - namecache_enable(); /* Enable netbios namecache */ - - /* Check winbindd parameters are valid */ - - ZERO_STRUCT(server_state); - - if (!winbindd_param_init()) - return False; - - /* Winbind daemon initialisation */ - - if (!winbindd_idmap_init()) - return False; - - /* Unblock all signals we are interested in as they may have been - blocked by the parent process. */ - - BlockSignals(False, SIGINT); - BlockSignals(False, SIGQUIT); - BlockSignals(False, SIGTERM); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGUSR2); - BlockSignals(False, SIGHUP); - - /* Setup signal handlers */ - - CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ - CatchSignal(SIGQUIT, termination_handler); - CatchSignal(SIGTERM, termination_handler); - - CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ - - CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ - CatchSignal(SIGHUP, sighup_handler); - - return True; -} - - -/* Main function */ - -struct winbindd_state server_state; /* Server state information */ - - -static void usage(void) -{ - printf("Usage: winbindd [options]\n"); - printf("\t-F daemon in foreground mode\n"); - printf("\t-S log to stdout\n"); - printf("\t-i interactive mode\n"); - printf("\t-B dual daemon mode\n"); - printf("\t-n disable cacheing\n"); - printf("\t-d level set debug level\n"); - printf("\t-s configfile choose smb.conf location\n"); - printf("\t-h show this help message\n"); -} - - int main(int argc, char **argv) -{ - extern BOOL AllowDebugChange; - pstring logfile; - BOOL interactive = False; - BOOL Fork = True; - BOOL log_stdout = False; - int opt; - - /* glibc (?) likes to print "User defined signal 1" and exit if a - SIGUSR[12] is received before a handler is installed */ - - CatchSignal(SIGUSR1, SIG_IGN); - CatchSignal(SIGUSR2, SIG_IGN); - - fault_setup((void (*)(void *))fault_quit ); - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - /* Initialise for running in non-root mode */ - - sec_init(); - - /* Set environment variable so we don't recursively call ourselves. - This may also be useful interactively. */ - - setenv(WINBINDD_DONT_ENV, "1", 1); - - /* Initialise samba/rpc client stuff */ - - while ((opt = getopt(argc, argv, "FSid:s:nhB")) != EOF) { - switch (opt) { - - case 'F': - Fork = False; - break; - case 'S': - log_stdout = True; - break; - /* Don't become a daemon */ - case 'i': - interactive = True; - log_stdout = True; - Fork = False; - break; - - /* dual daemon system */ - case 'B': - opt_dual_daemon = True; - break; - - /* disable cacheing */ - case 'n': - opt_nocache = True; - break; - - /* Run with specified debug level */ - case 'd': - DEBUGLEVEL = atoi(optarg); - AllowDebugChange = False; - break; - - /* Load a different smb.conf file */ - case 's': - pstrcpy(dyn_CONFIGFILE,optarg); - break; - - case 'h': - usage(); - exit(0); - - default: - printf("Unknown option %c\n", (char)opt); - exit(1); - } - } - - if (log_stdout && Fork) { - printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n"); - usage(); - exit(1); - } - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - setup_logging("winbindd", log_stdout?DEBUG_STDOUT:DEBUG_FILE); - reopen_logs(); - - DEBUG(1, ("winbindd version %s started.\n", VERSION ) ); - DEBUGADD( 1, ( "Copyright The Samba Team 2000-2001\n" ) ); - - if (!reload_services_file(False)) { - DEBUG(0, ("error opening config file\n")); - exit(1); - } - - /* Setup names. */ - - if (!init_names()) - exit(1); - - if (!interactive) { - become_daemon(Fork); - pidfile_create("winbindd"); - } - - -#if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (interactive) - setpgid( (pid_t)0, (pid_t)0); -#endif - - if (!winbind_setup_common()) { - return 1; - } - - if (opt_dual_daemon) { - do_dual_daemon(); - } - - /* Initialise messaging system */ - - if (!message_init()) { - DEBUG(0, ("unable to initialise messaging system\n")); - exit(1); - } - - register_msg_pool_usage(); - message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info); - - /* Loop waiting for requests */ - - process_loop(); - - trustdom_cache_shutdown(); - uni_group_cache_shutdown(); - return 0; -} diff --git a/source4/nsswitch/winbindd.h b/source4/nsswitch/winbindd.h deleted file mode 100644 index 42ef209faf..0000000000 --- a/source4/nsswitch/winbindd.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifndef _WINBINDD_H -#define _WINBINDD_H - -#include "includes.h" -#include "nterr.h" - -#include "winbindd_nss.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Client state structure */ - -struct winbindd_cli_state { - struct winbindd_cli_state *prev, *next; /* Linked list pointers */ - int sock; /* Open socket from client */ - pid_t pid; /* pid of client */ - int read_buf_len, write_buf_len; /* Indexes in request/response */ - BOOL finished; /* Can delete from list */ - BOOL write_extra_data; /* Write extra_data field */ - time_t last_access; /* Time of last access (read or write) */ - struct winbindd_request request; /* Request from client */ - struct winbindd_response response; /* Respose to client */ - struct getent_state *getpwent_state; /* State for getpwent() */ - struct getent_state *getgrent_state; /* State for getgrent() */ -}; - -/* State between get{pw,gr}ent() calls */ - -struct getent_state { - struct getent_state *prev, *next; - void *sam_entries; - uint32 sam_entry_index, num_sam_entries; - BOOL got_sam_entries; - fstring domain_name; -}; - -/* Storage for cached getpwent() user entries */ - -struct getpwent_user { - fstring name; /* Account name */ - fstring gecos; /* User information */ - DOM_SID user_sid; /* NT user and primary group SIDs */ - DOM_SID group_sid; -}; - -/* Server state structure */ - -struct winbindd_state { - - /* User and group id pool */ - - uid_t uid_low, uid_high; /* Range of uids to allocate */ - gid_t gid_low, gid_high; /* Range of gids to allocate */ -}; - -extern struct winbindd_state server_state; /* Server information */ - -typedef struct { - char *acct_name; - char *full_name; - DOM_SID *user_sid; /* NT user and primary group SIDs */ - DOM_SID *group_sid; -} WINBIND_USERINFO; - -/* Structures to hold per domain information */ - -struct winbindd_domain { - fstring name; /* Domain name */ - fstring alt_name; /* alt Domain name (if any) */ - DOM_SID sid; /* SID for this domain */ - BOOL native_mode; /* is this a win2k domain in native mode ? */ - - /* Lookup methods for this domain (LDAP or RPC) */ - - struct winbindd_methods *methods; - - /* Private data for the backends (used for connection cache) */ - - void *private; - - /* Sequence number stuff */ - - time_t last_seq_check; - uint32 sequence_number; - - /* Linked list info */ - - struct winbindd_domain *prev, *next; -}; - -/* per-domain methods. This is how LDAP vs RPC is selected - */ -struct winbindd_methods { - /* does this backend provide a consistent view of the data? (ie. is the primary group - always correct) */ - BOOL consistent; - - /* get a list of users, returning a WINBIND_USERINFO for each one */ - NTSTATUS (*query_user_list)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info); - - /* get a list of domain groups */ - NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info); - - /* get a list of domain local groups */ - NTSTATUS (*enum_local_groups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info); - - /* convert one user or group name to a sid */ - NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type); - - /* convert a sid to a user or group name */ - NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type); - - /* lookup user info for a given SID */ - NTSTATUS (*query_user)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *user_info); - - /* lookup all groups that a user is a member of. The backend - can also choose to lookup by username or rid for this - function */ - NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids); - - /* find all members of the group with the specified group_rid */ - NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, - uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types); - - /* return the current global sequence number */ - NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq); - - /* enumerate trusted domains */ - NTSTATUS (*trusted_domains)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids); - - /* find the domain sid */ - NTSTATUS (*domain_sid)(struct winbindd_domain *domain, - DOM_SID *sid); - - /* setup the list of alternate names for the domain, if any */ - NTSTATUS (*alternate_name)(struct winbindd_domain *domain); -}; - -/* Used to glue a policy handle and cli_state together */ - -typedef struct { - struct cli_state *cli; - POLICY_HND pol; -} CLI_POLICY_HND; - -/* Filled out by IDMAP backends */ -struct idmap_methods { - /* Called when backend is first loaded */ - BOOL (*init)(void); - - BOOL (*get_sid_from_uid)(uid_t uid, DOM_SID *sid); - BOOL (*get_sid_from_gid)(gid_t gid, DOM_SID *sid); - - BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); - BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); - - /* Called when backend is unloaded */ - BOOL (*close)(void); - /* Called to dump backend status */ - void (*status)(void); -}; - -#include "winbindd_proto.h" - -#include "rpc_parse.h" -#include "rpc_client.h" - -#define WINBINDD_ESTABLISH_LOOP 30 -#define WINBINDD_RESCAN_FREQ 300 - -#define DOM_SEQUENCE_NONE ((uint32)-1) - -#endif /* _WINBINDD_H */ diff --git a/source4/nsswitch/winbindd_ads.c b/source4/nsswitch/winbindd_ads.c deleted file mode 100644 index de3757aa44..0000000000 --- a/source4/nsswitch/winbindd_ads.c +++ /dev/null @@ -1,837 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind ADS backend functions - - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003 - - 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 "winbindd.h" - -#ifdef HAVE_ADS - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* the realm of our primary LDAP server */ -static char *primary_realm; - - -/* - return our ads connections structure for a domain. We keep the connection - open to make things faster -*/ -static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) -{ - ADS_STRUCT *ads; - ADS_STATUS status; - - if (domain->private) { - return (ADS_STRUCT *)domain->private; - } - - /* we don't want this to affect the users ccache */ - setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1); - - ads = ads_init(domain->alt_name, domain->name, NULL); - if (!ads) { - DEBUG(1,("ads_init for domain %s failed\n", domain->name)); - return NULL; - } - - /* the machine acct password might have change - fetch it every time */ - SAFE_FREE(ads->auth.password); - ads->auth.password = secrets_fetch_machine_password(); - - if (primary_realm) { - SAFE_FREE(ads->auth.realm); - ads->auth.realm = strdup(primary_realm); - } - - status = ads_connect(ads); - if (!ADS_ERR_OK(status) || !ads->config.realm) { - extern struct winbindd_methods msrpc_methods; - DEBUG(1,("ads_connect for domain %s failed: %s\n", - domain->name, ads_errstr(status))); - ads_destroy(&ads); - - /* if we get ECONNREFUSED then it might be a NT4 - server, fall back to MSRPC */ - if (status.error_type == ADS_ERROR_SYSTEM && - status.err.rc == ECONNREFUSED) { - DEBUG(1,("Trying MSRPC methods\n")); - domain->methods = &msrpc_methods; - } - return NULL; - } - - /* remember our primary realm for trusted domain support */ - if (!primary_realm) { - primary_realm = strdup(ads->config.realm); - } - - domain->private = (void *)ads; - return ads; -} - - -/* Query display info for a realm. This is the basic user list fn */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", "objectSid", "primaryGroupID", - "sAMAccountType", NULL}; - int i, count; - ADS_STATUS rc; - void *res = NULL; - void *msg = NULL; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - - *num_entries = 0; - - DEBUG(3,("ads: query_user_list\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(1,("query_user_list: No users found\n")); - goto done; - } - - (*info) = talloc_zero(mem_ctx, count * sizeof(**info)); - if (!*info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - i = 0; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *name, *gecos; - DOM_SID sid; - DOM_SID *sid2; - DOM_SID *group_sid; - uint32 group; - uint32 atype; - - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || - ads_atype_map(atype) != SID_NAME_USER) { - DEBUG(1,("Not a user account? atype=0x%x\n", atype)); - continue; - } - - name = ads_pull_username(ads, mem_ctx, msg); - gecos = ads_pull_string(ads, mem_ctx, msg, "name"); - if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %s !?\n", name)); - continue; - } - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) { - DEBUG(1,("No primary group for %s !?\n", name)); - continue; - } - - sid2 = talloc(mem_ctx, sizeof(*sid2)); - if (!sid2) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy(sid2, &sid); - - group_sid = rid_to_talloced_sid(domain, mem_ctx, group); - - (*info)[i].acct_name = name; - (*info)[i].full_name = gecos; - (*info)[i].user_sid = sid2; - (*info)[i].group_sid = group_sid; - i++; - } - - (*num_entries) = i; - status = NT_STATUS_OK; - - DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries))); - -done: - if (res) ads_msgfree(ads, res); - - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "name", "objectSid", - "sAMAccountType", NULL}; - int i, count; - ADS_STATUS rc; - void *res = NULL; - void *msg = NULL; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - uint32 group_flags; - - *num_entries = 0; - - DEBUG(3,("ads: enum_dom_groups\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(1,("enum_dom_groups: No groups found\n")); - goto done; - } - - (*info) = talloc_zero(mem_ctx, count * sizeof(**info)); - if (!*info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - i = 0; - - group_flags = ATYPE_GLOBAL_GROUP; - if ( domain->native_mode ) - group_flags |= ATYPE_LOCAL_GROUP; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *name, *gecos; - DOM_SID sid; - uint32 rid; - uint32 account_type; - - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &account_type) || !(account_type & group_flags) ) - continue; - - name = ads_pull_username(ads, mem_ctx, msg); - gecos = ads_pull_string(ads, mem_ctx, msg, "name"); - if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %s !?\n", name)); - continue; - } - - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { - DEBUG(1,("No rid for %s !?\n", name)); - continue; - } - - fstrcpy((*info)[i].acct_name, name); - fstrcpy((*info)[i].acct_desc, gecos); - (*info)[i].rid = rid; - i++; - } - - (*num_entries) = i; - - status = NT_STATUS_OK; - - DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries))); - -done: - if (res) ads_msgfree(ads, res); - - return status; -} - -/* list all domain local groups */ -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - /* - * This is a stub function only as we returned the domain - * ocal groups in enum_dom_groups() if the domain->native field - * was true. This is a simple performance optimization when - * using LDAP. - * - * if we ever need to enumerate domain local groups separately, - * then this the optimization in enum_dom_groups() will need - * to be split out - */ - *num_entries = 0; - - return NT_STATUS_OK; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads; - - DEBUG(3,("ads: name_to_sid\n")); - - ads = ads_cached_connection(domain); - if (!ads) - return NT_STATUS_UNSUCCESSFUL; - - return ads_name_to_sid(ads, name, sid, type); -} - -/* convert a sid to a user or group name */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads = NULL; - DEBUG(3,("ads: sid_to_name\n")); - ads = ads_cached_connection(domain); - if (!ads) - return NT_STATUS_UNSUCCESSFUL; - - return ads_sid_to_name(ads, mem_ctx, sid, name, type); -} - - -/* convert a DN to a name, SID and name type - this might become a major speed bottleneck if groups have - lots of users, in which case we could cache the results -*/ -static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - const char *dn, - char **name, uint32 *name_type, DOM_SID *sid) -{ - char *exp; - void *res = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "objectSid", "sAMAccountType", NULL}; - ADS_STATUS rc; - uint32 atype; - char *escaped_dn = escape_ldap_string_alloc(dn); - - if (!escaped_dn) { - return False; - } - - asprintf(&exp, "(distinguishedName=%s)", dn); - rc = ads_search_retry(ads, &res, exp, attrs); - SAFE_FREE(exp); - SAFE_FREE(escaped_dn); - - if (!ADS_ERR_OK(rc)) { - goto failed; - } - - (*name) = ads_pull_username(ads, mem_ctx, res); - - if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) { - goto failed; - } - (*name_type) = ads_atype_map(atype); - - if (!ads_pull_sid(ads, res, "objectSid", sid)) { - goto failed; - } - - if (res) ads_msgfree(ads, res); - return True; - -failed: - if (res) ads_msgfree(ads, res); - return False; -} - -/* Lookup user information from a rid */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - WINBIND_USERINFO *info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", - "primaryGroupID", NULL}; - ADS_STATUS rc; - int count; - void *msg = NULL; - char *exp; - char *sidstr; - uint32 group_rid; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - DOM_SID *sid2; - fstring sid_string; - - DEBUG(3,("ads: query_user\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - sidstr = sid_binstring(sid); - asprintf(&exp, "(objectSid=%s)", sidstr); - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); - free(sidstr); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, msg); - if (count != 1) { - DEBUG(1,("query_user(sid=%s): Not found\n", sid_to_string(sid_string, sid))); - goto done; - } - - info->acct_name = ads_pull_username(ads, mem_ctx, msg); - info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); - - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { - DEBUG(1,("No primary group for %s !?\n", sid_to_string(sid_string, sid))); - goto done; - } - - sid2 = talloc(mem_ctx, sizeof(*sid2)); - if (!sid2) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - sid_copy(sid2, sid); - - info->user_sid = sid2; - - info->group_sid = rid_to_talloced_sid(domain, mem_ctx, group_rid); - - status = NT_STATUS_OK; - - DEBUG(3,("ads query_user gave %s\n", info->acct_name)); -done: - if (msg) ads_msgfree(ads, msg); - - return status; -} - -/* Lookup groups a user is a member of - alternate method, for when - tokenGroups are not available. */ -static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *user_dn, - DOM_SID *primary_group, - uint32 *num_groups, DOM_SID ***user_gids) -{ - ADS_STATUS rc; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - int count; - void *res = NULL; - void *msg = NULL; - char *exp; - ADS_STRUCT *ads; - const char *group_attrs[] = {"objectSid", NULL}; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - /* buggy server, no tokenGroups. Instead lookup what groups this user - is a member of by DN search on member*/ - if (asprintf(&exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) { - DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); - return NT_STATUS_NO_MEMORY; - } - - rc = ads_search_retry(ads, &res, exp, group_attrs); - free(exp); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); - return ads_ntstatus(rc); - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(5,("lookup_usergroups: No supp groups found\n")); - - status = ads_ntstatus(rc); - goto done; - } - - (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); - (*user_gids)[0] = primary_group; - - *num_groups = 1; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - DOM_SID group_sid; - - if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) { - DEBUG(1,("No sid for this group ?!?\n")); - continue; - } - - if (sid_equal(&group_sid, primary_group)) continue; - - (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); - if (!(*user_gids)[*num_groups]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy((*user_gids)[*num_groups], &group_sid); - - (*num_groups)++; - - } - - status = NT_STATUS_OK; - - DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn)); -done: - if (res) ads_msgfree(ads, res); - if (msg) ads_msgfree(ads, msg); - - return status; -} - -/* Lookup groups a user is a member of. */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"distinguishedName", NULL}; - const char *attrs2[] = {"tokenGroups", "primaryGroupID", NULL}; - ADS_STATUS rc; - int count; - void *msg = NULL; - char *exp; - char *user_dn; - DOM_SID *sids; - int i; - DOM_SID *primary_group; - uint32 primary_group_rid; - char *sidstr; - fstring sid_string; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - - DEBUG(3,("ads: lookup_usergroups\n")); - *num_groups = 0; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - if (!(sidstr = sid_binstring(sid))) { - DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid))); - status = NT_STATUS_NO_MEMORY; - goto done; - } - if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { - free(sidstr); - DEBUG(1,("lookup_usergroups(sid=%s) asprintf failed!\n", sid_to_string(sid_string, sid))); - status = NT_STATUS_NO_MEMORY; - goto done; - } - - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); - free(sidstr); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); - if (!user_dn) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search did not return a a distinguishedName!\n", sid_to_string(sid_string, sid))); - if (msg) ads_msgfree(ads, msg); - goto done; - } - - if (msg) ads_msgfree(ads, msg); - - rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) { - DEBUG(1,("%s: No primary group for sid=%s !?\n", domain->name, sid_to_string(sid_string, sid))); - goto done; - } - - primary_group = rid_to_talloced_sid(domain, mem_ctx, primary_group_rid); - - count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); - - if (msg) ads_msgfree(ads, msg); - - /* there must always be at least one group in the token, - unless we are talking to a buggy Win2k server */ - if (count == 0) { - return lookup_usergroups_alt(domain, mem_ctx, user_dn, - primary_group, - num_groups, user_gids); - } - - (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); - (*user_gids)[0] = primary_group; - - *num_groups = 1; - - for (i=0;i<count;i++) { - if (sid_equal(&sids[i], primary_group)) continue; - - (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); - if (!(*user_gids)[*num_groups]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy((*user_gids)[*num_groups], &sids[i]); - (*num_groups)++; - } - - status = NT_STATUS_OK; - DEBUG(3,("ads lookup_usergroups for sid=%s\n", sid_to_string(sid_string, sid))); -done: - return status; -} - -/* - find the members of a group, given a group rid and domain - */ -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - ADS_STATUS rc; - int count; - void *res=NULL; - ADS_STRUCT *ads = NULL; - char *exp; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - char *sidstr; - const char *attrs[] = {"member", NULL}; - char **members; - int i, num_members; - fstring sid_string; - - *num_names = 0; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - sidstr = sid_binstring(group_sid); - - /* search for all members of the group */ - asprintf(&exp, "(objectSid=%s)",sidstr); - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); - free(sidstr); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - status = NT_STATUS_OK; - goto done; - } - - members = ads_pull_strings(ads, mem_ctx, res, "member"); - if (!members) { - /* no members? ok ... */ - status = NT_STATUS_OK; - goto done; - } - - /* now we need to turn a list of members into rids, names and name types - the problem is that the members are in the form of distinguised names - */ - for (i=0;members[i];i++) /* noop */ ; - num_members = i; - - (*sid_mem) = talloc_zero(mem_ctx, sizeof(**sid_mem) * num_members); - (*name_types) = talloc_zero(mem_ctx, sizeof(**name_types) * num_members); - (*names) = talloc_zero(mem_ctx, sizeof(**names) * num_members); - - for (i=0;i<num_members;i++) { - uint32 name_type; - char *name; - DOM_SID sid; - - if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &sid)) { - (*names)[*num_names] = name; - (*name_types)[*num_names] = name_type; - (*sid_mem)[*num_names] = talloc(mem_ctx, sizeof(***sid_mem)); - if (!(*sid_mem)[*num_names]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - sid_copy((*sid_mem)[*num_names], &sid); - (*num_names)++; - } - } - - status = NT_STATUS_OK; - DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid))); -done: - if (res) ads_msgfree(ads, res); - - return status; -} - - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - ADS_STRUCT *ads = NULL; - ADS_STATUS rc; - - *seq = DOM_SEQUENCE_NONE; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_USN(ads, seq); - if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); - domain->private = NULL; - } - return ads_ntstatus(rc); -} - -/* get a list of trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - - *num_domains = 0; - *names = NULL; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids); - - return ads_ntstatus(rc); -} - -/* find the domain sid for a domain */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_domain_sid(ads, sid); - - if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); - domain->private = NULL; - } - - return ads_ntstatus(rc); -} - - -/* find alternate names list for the domain - for ADS this is the - netbios name */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - TALLOC_CTX *ctx; - char *workgroup; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - if (!(ctx = talloc_init("alternate_name"))) { - return NT_STATUS_NO_MEMORY; - } - - rc = ads_workgroup_name(ads, ctx, &workgroup); - - if (ADS_ERR_OK(rc)) { - fstrcpy(domain->name, workgroup); - fstrcpy(domain->alt_name, ads->config.realm); - strupper(domain->alt_name); - strupper(domain->name); - } - - talloc_destroy(ctx); - - return ads_ntstatus(rc); -} - -/* the ADS backend methods are exposed via this structure */ -struct winbindd_methods ads_methods = { - True, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; - -#endif diff --git a/source4/nsswitch/winbindd_cache.c b/source4/nsswitch/winbindd_cache.c deleted file mode 100644 index 5fb59e7467..0000000000 --- a/source4/nsswitch/winbindd_cache.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind cache backend functions - - Copyright (C) Andrew Tridgell 2001 - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -struct winbind_cache { - struct winbindd_methods *backend; - TDB_CONTEXT *tdb; -}; - -struct cache_entry { - NTSTATUS status; - uint32 sequence_number; - uint8 *data; - uint32 len, ofs; -}; - -#define WINBINDD_MAX_CACHE_SIZE (50*1024*1024) - -static struct winbind_cache *wcache; - -/* flush the cache */ -void wcache_flush_cache(void) -{ - extern BOOL opt_nocache; - - if (!wcache) return; - if (wcache->tdb) { - tdb_close(wcache->tdb); - wcache->tdb = NULL; - } - if (opt_nocache) return; - - wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, - TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600); - - if (!wcache->tdb) { - DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); - } -} - -void winbindd_check_cache_size(time_t t) -{ - static time_t last_check_time; - struct stat st; - - if (last_check_time == (time_t)0) - last_check_time = t; - - if (t - last_check_time < 60 && t - last_check_time > 0) - return; - - if (wcache == NULL || wcache->tdb == NULL) { - DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n")); - return; - } - - if (fstat(wcache->tdb->fd, &st) == -1) { - DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) )); - return; - } - - if (st.st_size > WINBINDD_MAX_CACHE_SIZE) { - DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n", - (unsigned long)st.st_size, - (unsigned long)WINBINDD_MAX_CACHE_SIZE)); - wcache_flush_cache(); - } -} - -/* get the winbind_cache structure */ -static struct winbind_cache *get_cache(struct winbindd_domain *domain) -{ - extern struct winbindd_methods msrpc_methods; - struct winbind_cache *ret = wcache; - - if (ret) return ret; - - ret = smb_xmalloc(sizeof(*ret)); - ZERO_STRUCTP(ret); - switch (lp_security()) { -#ifdef HAVE_ADS - case SEC_ADS: { - extern struct winbindd_methods ads_methods; - ret->backend = &ads_methods; - break; - } -#endif - default: - ret->backend = &msrpc_methods; - } - - wcache = ret; - wcache_flush_cache(); - - return ret; -} - -/* - free a centry structure -*/ -static void centry_free(struct cache_entry *centry) -{ - if (!centry) return; - SAFE_FREE(centry->data); - free(centry); -} - - -/* - pull a uint32 from a cache entry -*/ -static uint32 centry_uint32(struct cache_entry *centry) -{ - uint32 ret; - if (centry->len - centry->ofs < 4) { - DEBUG(0,("centry corruption? needed 4 bytes, have %d\n", - centry->len - centry->ofs)); - smb_panic("centry_uint32"); - } - ret = IVAL(centry->data, centry->ofs); - centry->ofs += 4; - return ret; -} - -/* - pull a uint8 from a cache entry -*/ -static uint8 centry_uint8(struct cache_entry *centry) -{ - uint8 ret; - if (centry->len - centry->ofs < 1) { - DEBUG(0,("centry corruption? needed 1 bytes, have %d\n", - centry->len - centry->ofs)); - smb_panic("centry_uint32"); - } - ret = CVAL(centry->data, centry->ofs); - centry->ofs += 1; - return ret; -} - -/* pull a string from a cache entry, using the supplied - talloc context -*/ -static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx) -{ - uint32 len; - char *ret; - - len = centry_uint8(centry); - - if (len == 0xFF) { - /* a deliberate NULL string */ - return NULL; - } - - if (centry->len - centry->ofs < len) { - DEBUG(0,("centry corruption? needed %d bytes, have %d\n", - len, centry->len - centry->ofs)); - smb_panic("centry_string"); - } - - ret = talloc(mem_ctx, len+1); - if (!ret) { - smb_panic("centry_string out of memory\n"); - } - memcpy(ret,centry->data + centry->ofs, len); - ret[len] = 0; - centry->ofs += len; - return ret; -} - -/* pull a string from a cache entry, using the supplied - talloc context -*/ -static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx) -{ - DOM_SID *sid; - char *sid_string; - sid = talloc(mem_ctx, sizeof(*sid)); - if (!sid) return NULL; - - sid_string = centry_string(centry, mem_ctx); - if (!string_to_sid(sid, sid_string)) { - return NULL; - } - return sid; -} - -/* the server is considered down if it can't give us a sequence number */ -static BOOL wcache_server_down(struct winbindd_domain *domain) -{ - if (!wcache->tdb) return False; - return (domain->sequence_number == DOM_SEQUENCE_NONE); -} - - -/* - refresh the domain sequence number. If force is True - then always refresh it, no matter how recently we fetched it -*/ -static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) -{ - NTSTATUS status; - unsigned time_diff; - unsigned cache_time = lp_winbind_cache_time(); - - /* trying to reconnect is expensive, don't do it too often */ - if (domain->sequence_number == DOM_SEQUENCE_NONE) { - cache_time *= 8; - } - - time_diff = time(NULL) - domain->last_seq_check; - - /* see if we have to refetch the domain sequence number */ - if (!force && (time_diff < cache_time)) { - return; - } - - status = wcache->backend->sequence_number(domain, &domain->sequence_number); - - if (!NT_STATUS_IS_OK(status)) { - domain->sequence_number = DOM_SEQUENCE_NONE; - } - - domain->last_seq_check = time(NULL); -} - -/* - decide if a cache entry has expired -*/ -static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *centry) -{ - /* if the server is OK and our cache entry came from when it was down then - the entry is invalid */ - if (domain->sequence_number != DOM_SEQUENCE_NONE && - centry->sequence_number == DOM_SEQUENCE_NONE) { - return True; - } - - /* if the server is down or the cache entry is not older than the - current sequence number then it is OK */ - if (wcache_server_down(domain) || - centry->sequence_number == domain->sequence_number) { - return False; - } - - /* it's expired */ - return True; -} - -/* - fetch an entry from the cache, with a varargs key. auto-fetch the sequence - number and return status -*/ -static struct cache_entry *wcache_fetch(struct winbind_cache *cache, - struct winbindd_domain *domain, - const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static struct cache_entry *wcache_fetch(struct winbind_cache *cache, - struct winbindd_domain *domain, - const char *format, ...) -{ - va_list ap; - char *kstr; - TDB_DATA data; - struct cache_entry *centry; - TDB_DATA key; - - refresh_sequence_number(domain, False); - - va_start(ap, format); - smb_xvasprintf(&kstr, format, ap); - va_end(ap); - - key.dptr = kstr; - key.dsize = strlen(kstr); - data = tdb_fetch(wcache->tdb, key); - free(kstr); - if (!data.dptr) { - /* a cache miss */ - return NULL; - } - - centry = smb_xmalloc(sizeof(*centry)); - centry->data = data.dptr; - centry->len = data.dsize; - centry->ofs = 0; - - if (centry->len < 8) { - /* huh? corrupt cache? */ - centry_free(centry); - return NULL; - } - - centry->status = NT_STATUS(centry_uint32(centry)); - centry->sequence_number = centry_uint32(centry); - - if (centry_expired(domain, centry)) { - extern BOOL opt_dual_daemon; - - if (opt_dual_daemon) { - extern BOOL background_process; - background_process = True; - } else { - centry_free(centry); - return NULL; - } - } - - return centry; -} - -/* - make sure we have at least len bytes available in a centry -*/ -static void centry_expand(struct cache_entry *centry, uint32 len) -{ - uint8 *p; - if (centry->len - centry->ofs >= len) return; - centry->len *= 2; - p = realloc(centry->data, centry->len); - if (!p) { - DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len)); - smb_panic("out of memory in centry_expand"); - } - centry->data = p; -} - -/* - push a uint32 into a centry -*/ -static void centry_put_uint32(struct cache_entry *centry, uint32 v) -{ - centry_expand(centry, 4); - SIVAL(centry->data, centry->ofs, v); - centry->ofs += 4; -} - -/* - push a uint8 into a centry -*/ -static void centry_put_uint8(struct cache_entry *centry, uint8 v) -{ - centry_expand(centry, 1); - SCVAL(centry->data, centry->ofs, v); - centry->ofs += 1; -} - -/* - push a string into a centry - */ -static void centry_put_string(struct cache_entry *centry, const char *s) -{ - int len; - - if (!s) { - /* null strings are marked as len 0xFFFF */ - centry_put_uint8(centry, 0xFF); - return; - } - - len = strlen(s); - /* can't handle more than 254 char strings. Truncating is probably best */ - if (len > 254) len = 254; - centry_put_uint8(centry, len); - centry_expand(centry, len); - memcpy(centry->data + centry->ofs, s, len); - centry->ofs += len; -} - -static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) -{ - int len; - fstring sid_string; - centry_put_string(centry, sid_to_string(sid_string, sid)); -} - -/* - start a centry for output. When finished, call centry_end() -*/ -struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status) -{ - struct cache_entry *centry; - - if (!wcache->tdb) return NULL; - - centry = smb_xmalloc(sizeof(*centry)); - - centry->len = 8192; /* reasonable default */ - centry->data = smb_xmalloc(centry->len); - centry->ofs = 0; - centry->sequence_number = domain->sequence_number; - centry_put_uint32(centry, NT_STATUS_V(status)); - centry_put_uint32(centry, centry->sequence_number); - return centry; -} - -/* - finish a centry and write it to the tdb -*/ -static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3); -static void centry_end(struct cache_entry *centry, const char *format, ...) -{ - va_list ap; - char *kstr; - TDB_DATA key, data; - - va_start(ap, format); - smb_xvasprintf(&kstr, format, ap); - va_end(ap); - - key.dptr = kstr; - key.dsize = strlen(kstr); - data.dptr = centry->data; - data.dsize = centry->ofs; - - tdb_store(wcache->tdb, key, data, TDB_REPLACE); - free(kstr); -} - -static void wcache_save_name_to_sid(struct winbindd_domain *domain, - NTSTATUS status, - const char *name, DOM_SID *sid, - enum SID_NAME_USE type) -{ - struct cache_entry *centry; - uint32 len; - fstring uname; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - centry_put_sid(centry, sid); - fstrcpy(uname, name); - strupper(uname); - centry_end(centry, "NS/%s", sid_to_string(sid_string, sid)); - centry_free(centry); -} - -static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, - DOM_SID *sid, const char *name, enum SID_NAME_USE type) -{ - struct cache_entry *centry; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - if (NT_STATUS_IS_OK(status)) { - centry_put_uint32(centry, type); - centry_put_string(centry, name); - } - centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); - centry_free(centry); -} - - -static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info) -{ - struct cache_entry *centry; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - centry_put_string(centry, info->acct_name); - centry_put_string(centry, info->full_name); - centry_put_sid(centry, info->user_sid); - centry_put_sid(centry, info->group_sid); - centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid)); - centry_free(centry); -} - - -/* Query display info. This is the basic user list fn */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "UL/%s", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("query_user_list out of memory"); - for (i=0; i<(*num_entries); i++) { - (*info)[i].acct_name = centry_string(centry, mem_ctx); - (*info)[i].full_name = centry_string(centry, mem_ctx); - (*info)[i].user_sid = centry_sid(centry, mem_ctx); - (*info)[i].group_sid = centry_sid(centry, mem_ctx); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->query_user_list(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].full_name); - centry_put_sid(centry, (*info)[i].user_sid); - centry_put_sid(centry, (*info)[i].group_sid); - if (cache->backend->consistent) { - /* when the backend is consistent we can pre-prime some mappings */ - wcache_save_name_to_sid(domain, NT_STATUS_OK, - (*info)[i].acct_name, - (*info)[i].user_sid, - SID_NAME_USER); - wcache_save_sid_to_name(domain, NT_STATUS_OK, - (*info)[i].user_sid, - (*info)[i].acct_name, - SID_NAME_USER); - wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); - } - } - centry_end(centry, "UL/%s", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); - for (i=0; i<(*num_entries); i++) { - fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); - fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); - (*info)[i].rid = centry_uint32(centry); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].acct_desc); - centry_put_uint32(centry, (*info)[i].rid); - } - centry_end(centry, "GL/%s/domain", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); - for (i=0; i<(*num_entries); i++) { - fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); - fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); - (*info)[i].rid = centry_uint32(centry); - } - -do_cached: - - /* If we are returning cached data and the domain controller - is down then we don't know whether the data is up to date - or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to - indicate this. */ - - if (wcache_server_down(domain)) { - DEBUG(10, ("query_user_list: returning cached user list and server was down\n")); - status = NT_STATUS_MORE_PROCESSING_REQUIRED; - } else - status = centry->status; - - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->enum_local_groups(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].acct_desc); - centry_put_uint32(centry, (*info)[i].rid); - } - centry_end(centry, "GL/%s/local", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring uname; - DOM_SID *sid2; - - if (!cache->tdb) goto do_query; - - fstrcpy(uname, name); - strupper(uname); - centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); - if (!centry) goto do_query; - *type = centry_uint32(centry); - sid2 = centry_sid(centry, mem_ctx); - if (!sid2) { - ZERO_STRUCTP(sid); - } else { - sid_copy(sid, sid2); - } - - status = centry->status; - centry_free(centry); - return status; - -do_query: - ZERO_STRUCTP(sid); - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->name_to_sid(domain, mem_ctx, name, sid, type); - - /* and save it */ - wcache_save_name_to_sid(domain, status, name, sid, *type); - - /* We can't save the sid to name mapping as we don't know the - correct case of the name without looking it up */ - - return status; -} - -/* convert a sid to a user or group name. The sid is guaranteed to be in the domain - given */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); - if (!centry) goto do_query; - if (NT_STATUS_IS_OK(centry->status)) { - *type = centry_uint32(centry); - *name = centry_string(centry, mem_ctx); - } - status = centry->status; - centry_free(centry); - return status; - -do_query: - *name = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->sid_to_name(domain, mem_ctx, sid, name, type); - - /* and save it */ - refresh_sequence_number(domain, True); - wcache_save_sid_to_name(domain, status, sid, *name, *type); - wcache_save_name_to_sid(domain, status, *name, sid, *type); - - return status; -} - - -/* Lookup user information from a rid */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; - - info->acct_name = centry_string(centry, mem_ctx); - info->full_name = centry_string(centry, mem_ctx); - info->user_sid = centry_sid(centry, mem_ctx); - info->group_sid = centry_sid(centry, mem_ctx); - status = centry->status; - centry_free(centry); - return status; - -do_query: - ZERO_STRUCTP(info); - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->query_user(domain, mem_ctx, user_sid, info); - - /* and save it */ - refresh_sequence_number(domain, True); - wcache_save_user(domain, status, info); - - return status; -} - - -/* Lookup groups a user is a member of. */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; - - *num_groups = centry_uint32(centry); - - if (*num_groups == 0) goto do_cached; - - (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups)); - if (! (*user_gids)) smb_panic("lookup_usergroups out of memory"); - for (i=0; i<(*num_groups); i++) { - (*user_gids)[i] = centry_sid(centry, mem_ctx); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - (*num_groups) = 0; - (*user_gids) = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_groups); - for (i=0; i<(*num_groups); i++) { - centry_put_sid(centry, (*user_gids)[i]); - } - centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid)); - centry_free(centry); - -skip_save: - return status; -} - - -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); - if (!centry) goto do_query; - - *num_names = centry_uint32(centry); - - if (*num_names == 0) goto do_cached; - - (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names)); - (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names)); - (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names)); - - if (! (*sid_mem) || ! (*names) || ! (*name_types)) { - smb_panic("lookup_groupmem out of memory"); - } - - for (i=0; i<(*num_names); i++) { - (*sid_mem)[i] = centry_sid(centry, mem_ctx); - (*names)[i] = centry_string(centry, mem_ctx); - (*name_types)[i] = centry_uint32(centry); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - (*num_names) = 0; - (*sid_mem) = NULL; - (*names) = NULL; - (*name_types) = NULL; - - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, - sid_mem, names, name_types); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_names); - for (i=0; i<(*num_names); i++) { - centry_put_sid(centry, (*sid_mem)[i]); - centry_put_string(centry, (*names)[i]); - centry_put_uint32(centry, (*name_types)[i]); - } - centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid)); - centry_free(centry); - -skip_save: - return status; -} - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - refresh_sequence_number(domain, False); - - *seq = domain->sequence_number; - - return NT_STATUS_OK; -} - -/* enumerate trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->trusted_domains(domain, mem_ctx, num_domains, - names, alt_names, dom_sids); -} - -/* find the domain sid */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->domain_sid(domain, sid); -} - -/* find the alternate names for the domain, if any */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->alternate_name(domain); -} - -/* the ADS backend methods are exposed via this structure */ -struct winbindd_methods cache_methods = { - True, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; diff --git a/source4/nsswitch/winbindd_cm.c b/source4/nsswitch/winbindd_cm.c deleted file mode 100644 index 0748a1c534..0000000000 --- a/source4/nsswitch/winbindd_cm.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon connection manager - - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 2002 - - 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. -*/ - -/* - We need to manage connections to domain controllers without having to - mess up the main winbindd code with other issues. The aim of the - connection manager is to: - - - make connections to domain controllers and cache them - - re-establish connections when networks or servers go down - - centralise the policy on connection timeouts, domain controller - selection etc - - manage re-entrancy for when winbindd becomes able to handle - multiple outstanding rpc requests - - Why not have connection management as part of the rpc layer like tng? - Good question. This code may morph into libsmb/rpc_cache.c or something - like that but at the moment it's simply staying as part of winbind. I - think the TNG architecture of forcing every user of the rpc layer to use - the connection caching system is a bad idea. It should be an optional - method of using the routines. - - The TNG design is quite good but I disagree with some aspects of the - implementation. -tpot - - */ - -/* - TODO: - - - I'm pretty annoyed by all the make_nmb_name() stuff. It should be - moved down into another function. - - - There needs to be a utility function in libsmb/namequery.c that does - cm_get_dc_name() - - - Take care when destroying cli_structs as they can be shared between - various sam handles. - - */ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Global list of connections. Initially a DLIST but can become a hash - table or whatever later. */ - -struct winbindd_cm_conn { - struct winbindd_cm_conn *prev, *next; - fstring domain; - fstring controller; - fstring pipe_name; - size_t mutex_ref_count; - struct cli_state *cli; - POLICY_HND pol; -}; - -static struct winbindd_cm_conn *cm_conns = NULL; - -/* Get a domain controller name. Cache positive and negative lookups so we - don't go to the network too often when something is badly broken. */ - -#define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */ - -struct get_dc_name_cache { - fstring domain_name; - fstring srv_name; - time_t lookup_time; - struct get_dc_name_cache *prev, *next; -}; - -/* - find the DC for a domain using methods appropriate for a ADS domain -*/ -static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ - ADS_STRUCT *ads; - const char *realm = domain; - - if (strcasecmp(realm, lp_workgroup()) == 0) - realm = lp_realm(); - - ads = ads_init(realm, domain, NULL); - if (!ads) - return False; - - /* we don't need to bind, just connect */ - ads->auth.flags |= ADS_AUTH_NO_BIND; - - DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain)); - -#ifdef HAVE_ADS - /* a full ads_connect() is actually overkill, as we don't srictly need - to do the SASL auth in order to get the info we need, but libads - doesn't offer a better way right now */ - ads_connect(ads); -#endif - - if (!ads->config.realm) - return False; - - fstrcpy(srv_name, ads->config.ldap_server_name); - strupper(srv_name); - *dc_ip = ads->ldap_ip; - ads_destroy(&ads); - - DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n", - srv_name, inet_ntoa(*dc_ip))); - - return True; -} - - - -static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) -{ - static struct get_dc_name_cache *get_dc_name_cache; - struct get_dc_name_cache *dcc; - struct in_addr dc_ip; - BOOL ret; - - /* Check the cache for previous lookups */ - - for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) { - - if (!strequal(domain, dcc->domain_name)) - continue; /* Not our domain */ - - if ((time(NULL) - dcc->lookup_time) > - GET_DC_NAME_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain)); - - DLIST_REMOVE(get_dc_name_cache, dcc); - SAFE_FREE(dcc); - - break; - } - - /* Return a positive or negative lookup for this domain */ - - if (dcc->srv_name[0]) { - DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain)); - fstrcpy(srv_name, dcc->srv_name); - return True; - } else { - DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain)); - return False; - } - } - - /* Add cache entry for this lookup. */ - - DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain)); - - if (!(dcc = (struct get_dc_name_cache *) - malloc(sizeof(struct get_dc_name_cache)))) - return False; - - ZERO_STRUCTP(dcc); - - fstrcpy(dcc->domain_name, domain); - dcc->lookup_time = time(NULL); - - DLIST_ADD(get_dc_name_cache, dcc); - - zero_ip(&dc_ip); - - ret = False; - if (lp_security() == SEC_ADS) - ret = cm_ads_find_dc(domain, &dc_ip, srv_name); - - if (!ret) { - /* fall back on rpc methods if the ADS methods fail */ - ret = rpc_find_dc(domain, srv_name, &dc_ip); - } - - if (!ret) - return False; - - /* We have a name so make the cache entry positive now */ - fstrcpy(dcc->srv_name, srv_name); - - DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name, - inet_ntoa(dc_ip), domain)); - - *ip_out = dc_ip; - - return True; -} - -/* Choose between anonymous or authenticated connections. We need to use - an authenticated connection if DCs have the RestrictAnonymous registry - entry set > 0, or the "Additional restrictions for anonymous - connections" set in the win2k Local Security Policy. - - Caller to free() result in domain, username, password -*/ - -static void cm_get_ipc_userpass(char **username, char **domain, char **password) -{ - *username = secrets_fetch(SECRETS_AUTH_USER, NULL); - *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - - if (*username && **username) { - - if (!*domain || !**domain) - *domain = smb_xstrdup(lp_workgroup()); - - if (!*password || !**password) - *password = smb_xstrdup(""); - - DEBUG(3, ("IPC$ connections done by user %s\\%s\n", - *domain, *username)); - - } else { - DEBUG(3, ("IPC$ connections done anonymously\n")); - *username = smb_xstrdup(""); - *domain = smb_xstrdup(""); - *password = smb_xstrdup(""); - } -} - -/* Open a new smb pipe connection to a DC on a given domain. Cache - negative creation attempts so we don't try and connect to broken - machines too often. */ - -#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */ - -struct failed_connection_cache { - fstring domain_name; - fstring controller; - time_t lookup_time; - NTSTATUS nt_status; - struct failed_connection_cache *prev, *next; -}; - -static struct failed_connection_cache *failed_connection_cache; - -/* Add an entry to the failed conneciton cache */ - -static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, - NTSTATUS result) -{ - struct failed_connection_cache *fcc; - - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - - /* Check we already aren't in the cache */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - if (strequal(fcc->domain_name, new_conn->domain)) { - DEBUG(10, ("domain %s already tried and failed\n", - fcc->domain_name)); - return; - } - } - - /* Create negative lookup cache entry for this domain and controller */ - - if (!(fcc = (struct failed_connection_cache *) - malloc(sizeof(struct failed_connection_cache)))) { - DEBUG(0, ("malloc failed in add_failed_connection_entry!\n")); - return; - } - - ZERO_STRUCTP(fcc); - - fstrcpy(fcc->domain_name, new_conn->domain); - fstrcpy(fcc->controller, new_conn->controller); - fcc->lookup_time = time(NULL); - fcc->nt_status = result; - - DLIST_ADD(failed_connection_cache, fcc); -} - -/* Open a connction to the remote server, cache failures for 30 seconds */ - -static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, - struct winbindd_cm_conn *new_conn, BOOL keep_mutex) -{ - struct failed_connection_cache *fcc; - NTSTATUS result; - char *ipc_username, *ipc_domain, *ipc_password; - struct in_addr dc_ip; - int i; - BOOL retry = True; - BOOL got_mutex = False; - - ZERO_STRUCT(dc_ip); - - fstrcpy(new_conn->domain, domain); - fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index)); - - /* Look for a domain controller for this domain. Negative results - are cached so don't bother applying the caching for this - function just yet. */ - - if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) { - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(new_conn, result); - return result; - } - - /* Return false if we have tried to look up this domain and netbios - name before and failed. */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - - if (!(strequal(domain, fcc->domain_name) && - strequal(new_conn->controller, fcc->controller))) - continue; /* Not our domain */ - - if ((time(NULL) - fcc->lookup_time) > - FAILED_CONNECTION_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller)); - - DLIST_REMOVE(failed_connection_cache, fcc); - free(fcc); - - break; - } - - /* The timeout hasn't expired yet so return false */ - - DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller)); - - result = fcc->nt_status; - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - return result; - } - - /* Initialise SMB connection */ - - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - - DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", - new_conn->controller, lp_netbios_name(), ipc_domain, ipc_username)); - - for (i = 0; retry && (i < 3); i++) { - - if (!secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME, &new_conn->mutex_ref_count)) { - DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller)); - result = NT_STATUS_POSSIBLE_DEADLOCK; - continue; - } - - got_mutex = True; - - result = cli_full_connection(&new_conn->cli, lp_netbios_name(), new_conn->controller, - &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, 0, &retry); - - if (NT_STATUS_IS_OK(result)) - break; - - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - got_mutex = False; - } - - SAFE_FREE(ipc_username); - SAFE_FREE(ipc_domain); - SAFE_FREE(ipc_password); - - if (!NT_STATUS_IS_OK(result)) { - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - add_failed_connection_entry(new_conn, result); - return result; - } - - if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; - /* - * only cache a failure if we are not trying to open the - * **win2k** specific lsarpc UUID. This could be an NT PDC - * and therefore a failure is normal. This should probably - * be abstracted to a check for 2k specific pipes and wondering - * if the PDC is an NT4 box. but since there is only one 2k - * specific UUID right now, i'm not going to bother. --jerry - */ - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - if ( !is_win2k_pipe(pipe_index) ) - add_failed_connection_entry(new_conn, result); - cli_shutdown(new_conn->cli); - return result; - } - - if ((got_mutex) && !keep_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - return NT_STATUS_OK; -} - -/* Return true if a connection is still alive */ - -static BOOL connection_ok(struct winbindd_cm_conn *conn) -{ - if (!conn) { - smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n"); - return False; - } - - if (!conn->cli) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli was null!"); - return False; - } - - if (!conn->cli->initialised) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli->initialised is False!"); - return False; - } - - if (conn->cli->fd == -1) { - DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n", - conn->controller, conn->domain, conn->pipe_name)); - return False; - } - - return True; -} - -/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ - -static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, - struct winbindd_cm_conn **conn_out, BOOL keep_mutex) -{ - struct winbindd_cm_conn *conn, conn_temp; - NTSTATUS result; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, pipe_name)) { - if (!connection_ok(conn)) { - if (conn->cli) - cli_shutdown(conn->cli); - ZERO_STRUCT(conn_temp); - conn_temp.next = conn->next; - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - conn = &conn_temp; /* Just to keep the loop moving */ - } else { - if (keep_mutex) { - if (!secrets_named_mutex(conn->controller, - WINBIND_SERVER_MUTEX_WAIT_TIME, &conn->mutex_ref_count)) - DEBUG(0,("get_connection_from_cache: mutex grab failed for %s\n", - conn->controller)); - } - break; - } - } - } - - if (!conn) { - if (!(conn = malloc(sizeof(*conn)))) - return NT_STATUS_NO_MEMORY; - - ZERO_STRUCTP(conn); - - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn, keep_mutex))) { - DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", - domain, pipe_name, nt_errstr(result))); - SAFE_FREE(conn); - return result; - } - DLIST_ADD(cm_conns, conn); - } - - *conn_out = conn; - return NT_STATUS_OK; -} - - -/********************************************************************************** -**********************************************************************************/ - -BOOL cm_check_for_native_mode_win2k( const char *domain ) -{ - NTSTATUS result; - struct winbindd_cm_conn conn; - DS_DOMINFO_CTR ctr; - BOOL ret = False; - - ZERO_STRUCT( conn ); - ZERO_STRUCT( ctr ); - - - if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn, False)) ) { - DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", - domain, nt_errstr(result))); - return False; - } - - if ( conn.cli ) { - if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, - conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { - ret = False; - goto done; - } - } - - if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) - && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) - ret = True; - -done: - if ( conn.cli ) - cli_shutdown( conn.cli ); - - return ret; -} - - - -/* Return a LSA policy handle on a domain */ - -CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_handle(char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#if 0 /* This code now *well* out of date */ - -/* Return a SAM domain policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a basic handle to open a domain handle from */ - - if (!cm_get_sam_handle(domain)) - return False; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC) - basic_conn = conn; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM; - conn->cli = basic_conn->cli; - - result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, - domain_sid, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain user */ - -CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid, - uint32 user_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_USER && - conn->pipe_data.samr.rid == user_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_USER; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = user_rid; - - result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, user_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain group */ - -CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid, - uint32 group_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP && - conn->pipe_data.samr.rid == group_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = group_rid; - - result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, group_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#endif - -/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the - netlogon pipe as no handle is returned. */ - -NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd, - struct cli_state **cli) -{ - NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - struct winbindd_cm_conn *conn; - uint32 neg_flags = 0x000001ff; - - if (!cli) - return NT_STATUS_INVALID_PARAMETER; - - /* Open an initial conection - keep the mutex. */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("error connecting to domain password server: %s\n", - nt_errstr(result))); - - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - /* Try again */ - result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return result; - } - } - - *cli = conn->cli; - - return result; -} - -/* Dump the current connection status */ - -static void dump_conn_list(void) -{ - struct winbindd_cm_conn *con; - - DEBUG(0, ("\tDomain Controller Pipe\n")); - - for(con = cm_conns; con; con = con->next) { - char *msg; - - /* Display pipe info */ - - if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) { - DEBUG(0, ("Error: not enough memory!\n")); - } else { - DEBUG(0, ("%s\n", msg)); - SAFE_FREE(msg); - } - } -} - -void winbindd_cm_status(void) -{ - /* List open connections */ - - DEBUG(0, ("winbindd connection manager status:\n")); - - if (cm_conns) - dump_conn_list(); - else - DEBUG(0, ("\tNo active connections\n")); -} diff --git a/source4/nsswitch/winbindd_dual.c b/source4/nsswitch/winbindd_dual.c deleted file mode 100644 index 207757bcea..0000000000 --- a/source4/nsswitch/winbindd_dual.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind background daemon - - Copyright (C) Andrew Tridgell 2002 - - 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. -*/ - -/* - the idea of the optional dual daemon mode is ot prevent slow domain - responses from clagging up the rest of the system. When in dual - daemon mode winbindd always responds to requests from cache if the - request is in cache, and if the cached answer is stale then it asks - the "dual daemon" to update the cache for that request - - */ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern BOOL opt_dual_daemon; -BOOL background_process = False; -int dual_daemon_pipe = -1; - - -/* a list of requests ready to be sent to the dual daemon */ -struct dual_list { - struct dual_list *next; - char *data; - int length; - int offset; -}; - -static struct dual_list *dual_list; -static struct dual_list *dual_list_end; - -/* - setup a select() including the dual daemon pipe - */ -int dual_select_setup(fd_set *fds, int maxfd) -{ - if (dual_daemon_pipe == -1 || - !dual_list) { - return maxfd; - } - - FD_SET(dual_daemon_pipe, fds); - if (dual_daemon_pipe > maxfd) { - maxfd = dual_daemon_pipe; - } - return maxfd; -} - - -/* - a hook called from the main winbindd select() loop to handle writes - to the dual daemon pipe -*/ -void dual_select(fd_set *fds) -{ - int n; - - if (dual_daemon_pipe == -1 || - !dual_list || - !FD_ISSET(dual_daemon_pipe, fds)) { - return; - } - - n = sys_write(dual_daemon_pipe, - &dual_list->data[dual_list->offset], - dual_list->length - dual_list->offset); - - if (n <= 0) { - /* the pipe is dead! fall back to normal operation */ - dual_daemon_pipe = -1; - return; - } - - dual_list->offset += n; - - if (dual_list->offset == dual_list->length) { - struct dual_list *next; - next = dual_list->next; - free(dual_list->data); - free(dual_list); - dual_list = next; - if (!dual_list) { - dual_list_end = NULL; - } - } -} - -/* - send a request to the background daemon - this is called for stale cached entries -*/ -void dual_send_request(struct winbindd_cli_state *state) -{ - struct dual_list *list; - - if (!background_process) return; - - list = malloc(sizeof(*list)); - if (!list) return; - - list->next = NULL; - list->data = memdup(&state->request, sizeof(state->request)); - list->length = sizeof(state->request); - list->offset = 0; - - if (!dual_list_end) { - dual_list = list; - dual_list_end = list; - } else { - dual_list_end->next = list; - dual_list_end = list; - } - - background_process = False; -} - - -/* -the main dual daemon -*/ -void do_dual_daemon(void) -{ - int fdpair[2]; - struct winbindd_cli_state state; - - if (pipe(fdpair) != 0) { - return; - } - - ZERO_STRUCT(state); - state.pid = getpid(); - - dual_daemon_pipe = fdpair[1]; - state.sock = fdpair[0]; - - if (fork() != 0) { - close(fdpair[0]); - return; - } - close(fdpair[1]); - - if (!winbind_setup_common()) - _exit(0); - - dual_daemon_pipe = -1; - opt_dual_daemon = False; - - while (1) { - /* free up any talloc memory */ - lp_talloc_free(); - main_loop_talloc_free(); - - /* fetch a request from the main daemon */ - winbind_client_read(&state); - - if (state.finished) { - /* we lost contact with our parent */ - exit(0); - } - - /* process full rquests */ - if (state.read_buf_len == sizeof(state.request)) { - DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd)); - - /* special handling for the stateful requests */ - switch (state.request.cmd) { - case WINBINDD_GETPWENT: - winbindd_setpwent(&state); - break; - - case WINBINDD_GETGRENT: - case WINBINDD_GETGRLST: - winbindd_setgrent(&state); - break; - default: - break; - } - - winbind_process_packet(&state); - SAFE_FREE(state.response.extra_data); - - free_getent_state(state.getpwent_state); - free_getent_state(state.getgrent_state); - state.getpwent_state = NULL; - state.getgrent_state = NULL; - } - } -} - diff --git a/source4/nsswitch/winbindd_group.c b/source4/nsswitch/winbindd_group.c deleted file mode 100644 index d06db5943c..0000000000 --- a/source4/nsswitch/winbindd_group.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Jeremy Allison 2001. - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/*************************************************************** - Empty static struct for negative caching. -****************************************************************/ - -/* Fill a grent structure from various other information */ - -static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name, - const char *gr_name, gid_t unix_gid) -{ - fstring full_group_name; - /* Fill in uid/gid */ - fill_domain_username(full_group_name, dom_name, gr_name); - - gr->gr_gid = unix_gid; - - /* Group name and password */ - - safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1); - safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1); - - return True; -} - -/* Fill in the group membership field of a NT group given by group_sid */ - -static BOOL fill_grent_mem(struct winbindd_domain *domain, - DOM_SID *group_sid, - enum SID_NAME_USE group_name_type, - int *num_gr_mem, char **gr_mem, int *gr_mem_len) -{ - DOM_SID **sid_mem = NULL; - uint32 num_names = 0; - uint32 *name_types = NULL; - unsigned int buf_len, buf_ndx, i; - char **names = NULL, *buf; - BOOL result = False; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - fstring sid_string; - - if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) - return False; - - /* Initialise group membership information */ - - DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid))); - - *num_gr_mem = 0; - - if (group_name_type != SID_NAME_DOM_GRP) { - DEBUG(1, ("SID %s in domain %s isn't a domain group\n", - sid_to_string(sid_string, group_sid), domain->name)); - goto done; - } - - /* Lookup group members */ - status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names, - &sid_mem, &names, &name_types); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n", - sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status))); - - goto done; - } - - DEBUG(10, ("looked up %d names\n", num_names)); - - if (DEBUGLEVEL >= 10) { - for (i = 0; i < num_names; i++) - DEBUG(10, ("\t%20s %s %d\n", names[i], sid_to_string(sid_string, sid_mem[i]), - name_types[i])); - } - - /* Add members to list */ - - buf = NULL; - buf_len = buf_ndx = 0; - - again: - - for (i = 0; i < num_names; i++) { - char *the_name; - fstring name; - int len; - - the_name = names[i]; - - DEBUG(10, ("processing name %s\n", the_name)); - - /* FIXME: need to cope with groups within groups. These - occur in Universal groups on a Windows 2000 native mode - server. */ - - if (name_types[i] != SID_NAME_USER) { - DEBUG(3, ("name %s isn't a domain user\n", the_name)); - continue; - } - - /* Don't bother with machine accounts */ - - if (the_name[strlen(the_name) - 1] == '$') { - DEBUG(10, ("%s is machine account\n", the_name)); - continue; - } - - /* Append domain name */ - - fill_domain_username(name, domain->name, the_name); - - len = strlen(name); - - /* Add to list or calculate buffer length */ - - if (!buf) { - buf_len += len + 1; /* List is comma separated */ - (*num_gr_mem)++; - DEBUG(10, ("buf_len + %d = %d\n", len + 1, buf_len)); - } else { - DEBUG(10, ("appending %s at ndx %d\n", name, len)); - safe_strcpy(&buf[buf_ndx], name, len); - buf_ndx += len; - buf[buf_ndx] = ','; - buf_ndx++; - } - } - - /* Allocate buffer */ - - if (!buf && buf_len != 0) { - if (!(buf = malloc(buf_len))) { - DEBUG(1, ("out of memory\n")); - result = False; - goto done; - } - memset(buf, 0, buf_len); - goto again; - } - - if (buf && buf_ndx > 0) { - buf[buf_ndx - 1] = '\0'; - } - - *gr_mem = buf; - *gr_mem_len = buf_len; - - DEBUG(10, ("num_mem = %d, len = %d, mem = %s\n", *num_gr_mem, - buf_len, *num_gr_mem ? buf : "NULL")); - result = True; - -done: - - talloc_destroy(mem_ctx); - - DEBUG(10, ("fill_grent_mem returning %d\n", result)); - - return result; -} - -/* Return a group structure from a group name */ - -enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) -{ - DOM_SID group_sid; - struct winbindd_domain *domain; - enum SID_NAME_USE name_type; - fstring name_domain, name_group; - char *tmp, *gr_mem; - gid_t gid; - int gr_mem_len; - - /* Ensure null termination */ - state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; - - DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid, - state->request.data.groupname)); - - /* Parse domain and groupname */ - - memset(name_group, 0, sizeof(fstring)); - - tmp = state->request.data.groupname; - if (!parse_domain_user(tmp, name_domain, name_group)) - return WINBINDD_ERROR; - - /* Get info for the domain */ - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not get domain sid for domain %s\n", - name_domain)); - return WINBINDD_ERROR; - } - - /* Get rid and name type from name */ - - if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid, - &name_type)) { - DEBUG(1, ("group %s in domain %s does not exist\n", - name_group, name_domain)); - return WINBINDD_ERROR; - } - - if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) { - DEBUG(1, ("name '%s' is not a local or domain group: %d\n", - name_group, name_type)); - return WINBINDD_ERROR; - } - - if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) { - DEBUG(1, ("error converting unix gid to sid\n")); - return WINBINDD_ERROR; - } - - if (!fill_grent(&state->response.data.gr, name_domain, - name_group, gid) || - !fill_grent_mem(domain, &group_sid, name_type, - &state->response.data.gr.num_gr_mem, - &gr_mem, &gr_mem_len)) { - return WINBINDD_ERROR; - } - - /* Group membership lives at start of extra data */ - - state->response.data.gr.gr_mem_ofs = 0; - - state->response.length += gr_mem_len; - state->response.extra_data = gr_mem; - - return WINBINDD_OK; -} - -/* Return a group structure from a gid number */ - -enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - DOM_SID group_sid; - enum SID_NAME_USE name_type; - fstring dom_name; - fstring group_name; - int gr_mem_len; - char *gr_mem; - - DEBUG(3, ("[%5d]: getgrgid %d\n", state->pid, - state->request.data.gid)); - - /* Bug out if the gid isn't in the winbind range */ - - if ((state->request.data.gid < server_state.gid_low) || - (state->request.data.gid > server_state.gid_high)) - return WINBINDD_ERROR; - - /* Get rid from gid */ - - if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &group_sid)) { - DEBUG(1, ("could not convert gid %d to rid\n", - state->request.data.gid)); - return WINBINDD_ERROR; - } - - /* Get name from sid */ - - if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) { - DEBUG(1, ("could not lookup sid\n")); - return WINBINDD_ERROR; - } - - if (!((name_type == SID_NAME_ALIAS) || - (name_type == SID_NAME_DOM_GRP))) { - DEBUG(1, ("name '%s' is not a local or domain group: %d\n", - group_name, name_type)); - return WINBINDD_ERROR; - } - - /* Fill in group structure */ - - domain = find_domain_from_sid(&group_sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return WINBINDD_ERROR; - } - - if (!fill_grent(&state->response.data.gr, dom_name, group_name, - state->request.data.gid) || - !fill_grent_mem(domain, &group_sid, name_type, - &state->response.data.gr.num_gr_mem, - &gr_mem, &gr_mem_len)) - return WINBINDD_ERROR; - - /* Group membership lives at start of extra data */ - - state->response.data.gr.gr_mem_ofs = 0; - - state->response.length += gr_mem_len; - state->response.extra_data = gr_mem; - - return WINBINDD_OK; -} - -/* - * set/get/endgrent functions - */ - -/* "Rewind" file pointer for group database enumeration */ - -enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - - DEBUG(3, ("[%5d]: setgrent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_groups()) - return WINBINDD_ERROR; - - /* Free old static data if it exists */ - - if (state->getgrent_state != NULL) { - free_getent_state(state->getgrent_state); - state->getgrent_state = NULL; - } - - /* Create sam pipes for each domain we know about */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - struct getent_state *domain_state; - - /* Create a state record for this domain */ - - if ((domain_state = (struct getent_state *) - malloc(sizeof(struct getent_state))) == NULL) { - DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n")); - return WINBINDD_ERROR; - } - - ZERO_STRUCTP(domain_state); - - fstrcpy(domain_state->domain_name, domain->name); - - /* Add to list of open domains */ - - DLIST_ADD(state->getgrent_state, domain_state); - } - - return WINBINDD_OK; -} - -/* Close file pointer to ntdom group database */ - -enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5d]: endgrent\n", state->pid)); - - free_getent_state(state->getgrent_state); - state->getgrent_state = NULL; - - return WINBINDD_OK; -} - -/* Get the list of domain groups and domain aliases for a domain. We fill in - the sam_entries and num_sam_entries fields with domain group information. - The dispinfo_ndx field is incremented to the index of the next group to - fetch. Return True if some groups were returned, False otherwise. */ - -#define MAX_FETCH_SAM_ENTRIES 100 - -static BOOL get_sam_group_entries(struct getent_state *ent) -{ - NTSTATUS status; - uint32 num_entries; - struct acct_info *name_list = NULL, *tmp_name_list = NULL; - TALLOC_CTX *mem_ctx; - BOOL result = False; - struct acct_info *sam_grp_entries = NULL; - struct winbindd_domain *domain; - - if (ent->got_sam_entries) - return False; - - if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)", - ent->domain_name))) { - DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n")); - return False; - } - - /* Free any existing group info */ - - SAFE_FREE(ent->sam_entries); - ent->num_sam_entries = 0; - ent->got_sam_entries = True; - - /* Enumerate domain groups */ - - num_entries = 0; - - if (!(domain = find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name)); - goto done; - } - - /* always get the domain global groups */ - - status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s\n", nt_errstr(status))); - result = False; - goto done; - } - - /* Copy entries into return buffer */ - - if (num_entries) { - if ( !(name_list = malloc(sizeof(struct acct_info) * num_entries)) ) { - DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n", - num_entries)); - result = False; - goto done; - } - memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) ); - } - - ent->num_sam_entries = num_entries; - - /* get the domain local groups if we are a member of - a native win2k domain */ - - if ( domain->native_mode && domain->methods->enum_local_groups ) - { - DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); - - status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - - if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n")); - num_entries = 0; - } - else - DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries)); - - /* Copy entries into return buffer */ - - if ( num_entries ) { - if ( !(tmp_name_list = Realloc( name_list, sizeof(struct acct_info) * (ent->num_sam_entries+num_entries))) ) - { - DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n", - num_entries)); - result = False; - SAFE_FREE( name_list ); - goto done; - } - - name_list = tmp_name_list; - - memcpy( &name_list[ent->num_sam_entries], sam_grp_entries, - num_entries * sizeof(struct acct_info) ); - } - - ent->num_sam_entries += num_entries; - } - - - /* Fill in remaining fields */ - - ent->sam_entries = name_list; - ent->sam_entry_index = 0; - - result = (ent->num_sam_entries > 0); - - done: - talloc_destroy(mem_ctx); - - return result; -} - -/* Fetch next group entry from ntdom database */ - -#define MAX_GETGRENT_GROUPS 500 - -enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) -{ - struct getent_state *ent; - struct winbindd_gr *group_list = NULL; - int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0; - char *new_extra_data, *gr_mem_list = NULL; - - DEBUG(3, ("[%5d]: getgrent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_groups()) - return WINBINDD_ERROR; - - num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries); - - if ((state->response.extra_data = - malloc(num_groups * sizeof(struct winbindd_gr))) == NULL) - return WINBINDD_ERROR; - - state->response.data.num_entries = 0; - - group_list = (struct winbindd_gr *)state->response.extra_data; - - if (!(ent = state->getgrent_state)) - return WINBINDD_ERROR; - - /* Start sending back groups */ - - for (i = 0; i < num_groups; i++) { - struct acct_info *name_list = NULL; - fstring domain_group_name; - uint32 result; - gid_t group_gid; - int gr_mem_len; - char *gr_mem, *new_gr_mem_list; - DOM_SID group_sid; - struct winbindd_domain *domain; - - /* Do we need to fetch another chunk of groups? */ - - tryagain: - - DEBUG(10, ("entry_index = %d, num_entries = %d\n", - ent->sam_entry_index, ent->num_sam_entries)); - - if (ent->num_sam_entries == ent->sam_entry_index) { - - while(ent && !get_sam_group_entries(ent)) { - struct getent_state *next_ent; - - DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name)); - - /* Free state information for this domain */ - - SAFE_FREE(ent->sam_entries); - - next_ent = ent->next; - DLIST_REMOVE(state->getgrent_state, ent); - - SAFE_FREE(ent); - ent = next_ent; - } - - /* No more domains */ - - if (!ent) - break; - } - - name_list = ent->sam_entries; - - if (!(domain = - find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); - result = False; - goto done; - } - - /* Lookup group info */ - - sid_copy(&group_sid, &domain->sid); - sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - - if (!winbindd_idmap_get_gid_from_sid( - &group_sid, - &group_gid)) { - - DEBUG(1, ("could not look up gid for group %s\n", - name_list[ent->sam_entry_index].acct_name)); - - ent->sam_entry_index++; - goto tryagain; - } - - DEBUG(10, ("got gid %d for group %x\n", group_gid, - name_list[ent->sam_entry_index].rid)); - - /* Fill in group entry */ - - fill_domain_username(domain_group_name, ent->domain_name, - name_list[ent->sam_entry_index].acct_name); - - result = fill_grent(&group_list[group_list_ndx], - ent->domain_name, - name_list[ent->sam_entry_index].acct_name, - group_gid); - - /* Fill in group membership entry */ - - if (result) { - DOM_SID member_sid; - group_list[group_list_ndx].num_gr_mem = 0; - gr_mem = NULL; - gr_mem_len = 0; - - /* Get group membership */ - if (state->request.cmd == WINBINDD_GETGRLST) { - result = True; - } else { - sid_copy(&member_sid, &domain->sid); - sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid); - result = fill_grent_mem( - domain, - &member_sid, - SID_NAME_DOM_GRP, - &group_list[group_list_ndx].num_gr_mem, - &gr_mem, &gr_mem_len); - } - } - - if (result) { - /* Append to group membership list */ - new_gr_mem_list = Realloc( - gr_mem_list, - gr_mem_list_len + gr_mem_len); - - if (!new_gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) { - DEBUG(0, ("out of memory\n")); - SAFE_FREE(gr_mem_list); - gr_mem_list_len = 0; - break; - } - - DEBUG(10, ("list_len = %d, mem_len = %d\n", - gr_mem_list_len, gr_mem_len)); - - gr_mem_list = new_gr_mem_list; - - memcpy(&gr_mem_list[gr_mem_list_len], gr_mem, - gr_mem_len); - - SAFE_FREE(gr_mem); - - group_list[group_list_ndx].gr_mem_ofs = - gr_mem_list_len; - - gr_mem_list_len += gr_mem_len; - } - - ent->sam_entry_index++; - - /* Add group to return list */ - - if (result) { - - DEBUG(10, ("adding group num_entries = %d\n", - state->response.data.num_entries)); - - group_list_ndx++; - state->response.data.num_entries++; - - state->response.length += - sizeof(struct winbindd_gr); - - } else { - DEBUG(0, ("could not lookup domain group %s\n", - domain_group_name)); - } - } - - /* Copy the list of group memberships to the end of the extra data */ - - if (group_list_ndx == 0) - goto done; - - new_extra_data = Realloc( - state->response.extra_data, - group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len); - - if (!new_extra_data) { - DEBUG(0, ("out of memory\n")); - group_list_ndx = 0; - SAFE_FREE(state->response.extra_data); - SAFE_FREE(gr_mem_list); - - return WINBINDD_ERROR; - } - - state->response.extra_data = new_extra_data; - - memcpy(&((char *)state->response.extra_data) - [group_list_ndx * sizeof(struct winbindd_gr)], - gr_mem_list, gr_mem_list_len); - - SAFE_FREE(gr_mem_list); - - state->response.length += gr_mem_list_len; - - DEBUG(10, ("returning %d groups, length = %d\n", - group_list_ndx, gr_mem_list_len)); - - /* Out of domains */ - - done: - - return (group_list_ndx > 0) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* List domain groups without mapping to unix ids */ - -enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) -{ - uint32 total_entries = 0; - struct winbindd_domain *domain; - char *extra_data = NULL; - char *ted = NULL; - unsigned int extra_data_len = 0, i; - - DEBUG(3, ("[%5d]: list groups\n", state->pid)); - - /* Enumerate over trusted domains */ - - for (domain = domain_list(); domain; domain = domain->next) { - struct getent_state groups; - - ZERO_STRUCT(groups); - - /* Get list of sam groups */ - ZERO_STRUCT(groups); - fstrcpy(groups.domain_name, domain->name); - - get_sam_group_entries(&groups); - - if (groups.num_sam_entries == 0) { - /* this domain is empty or in an error state */ - continue; - } - - /* keep track the of the total number of groups seen so - far over all domains */ - total_entries += groups.num_sam_entries; - - /* Allocate some memory for extra data. Note that we limit - account names to sizeof(fstring) = 128 characters. */ - ted = Realloc(extra_data, sizeof(fstring) * total_entries); - - if (!ted) { - DEBUG(0,("failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - return WINBINDD_ERROR; - } else - extra_data = ted; - - /* Pack group list into extra data fields */ - for (i = 0; i < groups.num_sam_entries; i++) { - char *group_name = ((struct acct_info *) - groups.sam_entries)[i].acct_name; - fstring name; - - fill_domain_username(name, domain->name, group_name); - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } - - free(groups.sam_entries); - } - - /* Assign extra_data fields in response structure */ - if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - /* No domains may have responded but that's still OK so don't - return an error. */ - - return WINBINDD_OK; -} - -/* Get user supplementary groups. This is much quicker than trying to - invert the groups database. */ - -enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) -{ - fstring name_domain, name_user; - DOM_SID user_sid; - enum SID_NAME_USE name_type; - uint32 num_groups, num_gids; - NTSTATUS status; - DOM_SID **user_gids; - struct winbindd_domain *domain; - enum winbindd_result result = WINBINDD_ERROR; - gid_t *gid_list; - unsigned int i; - TALLOC_CTX *mem_ctx; - - /* Ensure null termination */ - state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - - DEBUG(3, ("[%5d]: getgroups %s\n", state->pid, - state->request.data.username)); - - if (!(mem_ctx = talloc_init("winbindd_getgroups(%s)", - state->request.data.username))) - return WINBINDD_ERROR; - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) - goto done; - - /* Get info for the domain */ - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", - name_domain)); - goto done; - } - - /* Get rid and name type from name. The following costs 1 packet */ - - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, - &name_type)) { - DEBUG(1, ("user '%s' does not exist\n", name_user)); - goto done; - } - - if (name_type != SID_NAME_USER) { - DEBUG(1, ("name '%s' is not a user name: %d\n", - name_user, name_type)); - goto done; - } - - status = domain->methods->lookup_usergroups(domain, mem_ctx, - &user_sid, &num_groups, - &user_gids); - if (!NT_STATUS_IS_OK(status)) goto done; - - /* Copy data back to client */ - - num_gids = 0; - gid_list = malloc(sizeof(gid_t) * num_groups); - - if (state->response.extra_data) - goto done; - - for (i = 0; i < num_groups; i++) { - if (!winbindd_idmap_get_gid_from_sid( - user_gids[i], - &gid_list[num_gids])) { - fstring sid_string; - - DEBUG(1, ("unable to convert group sid %s to gid\n", - sid_to_string(sid_string, user_gids[i]))); - continue; - } - - num_gids++; - } - - state->response.data.num_entries = num_gids; - state->response.extra_data = gid_list; - state->response.length += num_gids * sizeof(gid_t); - - result = WINBINDD_OK; - - done: - - talloc_destroy(mem_ctx); - - return result; -} diff --git a/source4/nsswitch/winbindd_idmap.c b/source4/nsswitch/winbindd_idmap.c deleted file mode 100644 index de547cde41..0000000000 --- a/source4/nsswitch/winbindd_idmap.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Winbind ID Mapping - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003 - - 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 "winbindd.h" - -static struct { - const char *name; - /* Function to create a member of the idmap_methods list */ - BOOL (*reg_meth)(struct idmap_methods **methods); - struct idmap_methods *methods; -} builtin_idmap_functions[] = { - { "tdb", winbind_idmap_reg_tdb, NULL }, - /* { "ldap", winbind_idmap_reg_ldap, NULL },*/ - { NULL, NULL, NULL } -}; - -/* singleton pattern: uberlazy evaluation */ -static struct idmap_methods *impl; - -static struct idmap_methods *get_impl(const char *name) -{ - int i = 0; - struct idmap_methods *ret = NULL; - - while (builtin_idmap_functions[i].name && - strcmp(builtin_idmap_functions[i].name, name)) { - i++; - } - - if (builtin_idmap_functions[i].name) { - if (!builtin_idmap_functions[i].methods) { - builtin_idmap_functions[i].reg_meth(&builtin_idmap_functions[i].methods); - } - - ret = builtin_idmap_functions[i].methods; - } - - return ret; -} - -/* Initialize backend */ -BOOL winbindd_idmap_init(void) -{ - BOOL ret = False; - - DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n", - lp_idmap_backend())); - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->init(); - } - - DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false")); - - return ret; -} - -/* Get UID from SID */ -BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_uid_from_sid(sid, uid); - } - - return ret; -} - -/* Get GID from SID */ -BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_gid_from_sid(sid, gid); - } - - return ret; -} - -/* Get SID from UID */ -BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_sid_from_uid(uid, sid); - } - - return ret; -} - -/* Get SID from GID */ -BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->get_sid_from_gid(gid, sid); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - -/* Close backend */ -BOOL winbindd_idmap_close(void) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->close(); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - -/* Dump backend status */ -void winbindd_idmap_status(void) -{ - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - impl->status(); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } -} - diff --git a/source4/nsswitch/winbindd_idmap_tdb.c b/source4/nsswitch/winbindd_idmap_tdb.c deleted file mode 100644 index 911b3b41d2..0000000000 --- a/source4/nsswitch/winbindd_idmap_tdb.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - user related function - - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* High water mark keys */ -#define HWM_GROUP "GROUP HWM" -#define HWM_USER "USER HWM" - -/* idmap version determines auto-conversion */ -#define IDMAP_VERSION 2 - -/* Globals */ -static TDB_CONTEXT *idmap_tdb; - -/* convert one record to the new format */ -static int tdb_convert_fn(TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, - void *ignored) -{ - struct winbindd_domain *domain; - char *p; - DOM_SID sid; - uint32 rid; - fstring keystr; - fstring dom_name; - TDB_DATA key2; - - p = strchr(key.dptr, '/'); - if (!p) - return 0; - - *p = 0; - fstrcpy(dom_name, key.dptr); - *p++ = '/'; - - domain = find_domain_from_name(dom_name); - if (!domain) { - /* We must delete the old record. */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to find domain %s\n", - dom_name)); - DEBUG(0, - ("winbindd: tdb_convert_fn : deleting record %s\n", - key.dptr)); - tdb_delete(idmap_tdb, key); - return 0; - } - - rid = atoi(p); - - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); - - sid_to_string(keystr, &sid); - key2.dptr = keystr; - key2.dsize = strlen(keystr) + 1; - - if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) { - /* not good! */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to update record %s\n", - key2.dptr)); - DEBUG(0, - ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); - return -1; - } - - if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) { - /* not good! */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to update record %s\n", - data.dptr)); - DEBUG(0, - ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); - return -1; - } - - tdb_delete(idmap_tdb, key); - - return 0; -} - -/***************************************************************************** - Convert the idmap database from an older version. -*****************************************************************************/ -static BOOL tdb_idmap_convert(const char *idmap_name) -{ - int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); - BOOL bigendianheader = - (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; - - if (vers == IDMAP_VERSION) - return True; - - if (((vers == -1) && bigendianheader) - || (IREV(vers) == IDMAP_VERSION)) { - /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ - /* - * high and low records were created on a - * big endian machine and will need byte-reversing. - */ - - int32 wm; - - wm = tdb_fetch_int32(idmap_tdb, HWM_USER); - - if (wm != -1) { - wm = IREV(wm); - } else - wm = server_state.uid_low; - - if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap user hwm in idmap database\n")); - return False; - } - - wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); - if (wm != -1) { - wm = IREV(wm); - } else - wm = server_state.gid_low; - - if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); - return False; - } - } - - /* the old format stored as DOMAIN/rid - now we store the SID direct */ - tdb_traverse(idmap_tdb, tdb_convert_fn, NULL); - - if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == - -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); - return False; - } - - return True; -} - -/* Allocate either a user or group id from the pool */ -static BOOL tdb_allocate_id(uid_t * id, BOOL isgroup) -{ - int hwm; - - /* Get current high water mark */ - if ((hwm = tdb_fetch_int32(idmap_tdb, - isgroup ? HWM_GROUP : HWM_USER)) == - -1) { - return False; - } - - /* Return next available uid in list */ - if ((isgroup && (hwm > server_state.gid_high)) || - (!isgroup && (hwm > server_state.uid_high))) { - DEBUG(0, - ("winbind %sid range full!\n", isgroup ? "g" : "u")); - return False; - } - - if (id) { - *id = hwm; - } - - hwm++; - - /* Store new high water mark */ - tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm); - - return True; -} - -/* Get a sid from an id */ -static BOOL tdb_get_sid_from_id(int id, DOM_SID * sid, BOOL isgroup) -{ - TDB_DATA key, data; - fstring keystr; - BOOL result = False; - - slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID", - id); - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(idmap_tdb, key); - - if (data.dptr) { - result = string_to_sid(sid, data.dptr); - SAFE_FREE(data.dptr); - } - - return result; -} - -/* Get an id from a sid */ -static BOOL tdb_get_id_from_sid(DOM_SID * sid, uid_t * id, BOOL isgroup) -{ - TDB_DATA data, key; - fstring keystr; - BOOL result = False; - - /* Check if sid is present in database */ - sid_to_string(keystr, sid); - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(idmap_tdb, key); - - if (data.dptr) { - fstring scanstr; - int the_id; - - /* Parse and return existing uid */ - fstrcpy(scanstr, isgroup ? "GID" : "UID"); - fstrcat(scanstr, " %d"); - - if (sscanf(data.dptr, scanstr, &the_id) == 1) { - /* Store uid */ - if (id) { - *id = the_id; - } - - result = True; - } - - SAFE_FREE(data.dptr); - } else { - - /* Allocate a new id for this sid */ - if (id && tdb_allocate_id(id, isgroup)) { - fstring keystr2; - - /* Store new id */ - slprintf(keystr2, sizeof(keystr2), "%s %d", - isgroup ? "GID" : "UID", *id); - - data.dptr = keystr2; - data.dsize = strlen(keystr2) + 1; - - tdb_store(idmap_tdb, key, data, TDB_REPLACE); - tdb_store(idmap_tdb, data, key, TDB_REPLACE); - - result = True; - } - } - - return result; -} - -/***************************************************************************** - Initialise idmap database. -*****************************************************************************/ -static BOOL tdb_idmap_init(void) -{ - /* Open tdb cache */ - if (!(idmap_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0, - TDB_DEFAULT, O_RDWR | O_CREAT, - 0600))) { - DEBUG(0, - ("winbindd_idmap_init: Unable to open idmap database\n")); - return False; - } - - /* possibly convert from an earlier version */ - if (!tdb_idmap_convert(lock_path("winbindd_idmap.tdb"))) { - DEBUG(0, - ("winbindd_idmap_init: Unable to open idmap database\n")); - return False; - } - - /* Create high water marks for group and user id */ - if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) { - if (tdb_store_int32 - (idmap_tdb, HWM_USER, server_state.uid_low) == -1) { - DEBUG(0, - ("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n")); - return False; - } - } - - if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) { - if (tdb_store_int32 - (idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) { - DEBUG(0, - ("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n")); - return False; - } - } - - return True; -} - -/* Get a sid from a uid */ -static BOOL tdb_get_sid_from_uid(uid_t uid, DOM_SID * sid) -{ - return tdb_get_sid_from_id((int) uid, sid, False); -} - -/* Get a sid from a gid */ -static BOOL tdb_get_sid_from_gid(gid_t gid, DOM_SID * sid) -{ - return tdb_get_sid_from_id((int) gid, sid, True); -} - -/* Get a uid from a sid */ -static BOOL tdb_get_uid_from_sid(DOM_SID * sid, uid_t * uid) -{ - return tdb_get_id_from_sid(sid, uid, False); -} - -/* Get a gid from a group sid */ -static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid) -{ - return tdb_get_id_from_sid(sid, gid, True); -} - -/* Close the tdb */ -static BOOL tdb_idmap_close(void) -{ - if (idmap_tdb) - return (tdb_close(idmap_tdb) == 0); - return True; -} - - -/* Dump status information to log file. Display different stuff based on - the debug level: - - Debug Level Information Displayed - ================================================================= - 0 Percentage of [ug]id range allocated - 0 High water marks (next allocated ids) -*/ - -#define DUMP_INFO 0 - -static void tdb_idmap_status(void) -{ - int user_hwm, group_hwm; - - DEBUG(0, ("winbindd idmap status:\n")); - - /* Get current high water marks */ - - if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { - DEBUG(DUMP_INFO, - ("\tCould not get userid high water mark!\n")); - } - - if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { - DEBUG(DUMP_INFO, - ("\tCould not get groupid high water mark!\n")); - } - - /* Display next ids to allocate */ - - if (user_hwm != -1) { - DEBUG(DUMP_INFO, - ("\tNext userid to allocate is %d\n", user_hwm)); - } - - if (group_hwm != -1) { - DEBUG(DUMP_INFO, - ("\tNext groupid to allocate is %d\n", group_hwm)); - } - - /* Display percentage of id range already allocated. */ - - if (user_hwm != -1) { - int num_users = user_hwm - server_state.uid_low; - int total_users = - server_state.uid_high - server_state.uid_low; - - DEBUG(DUMP_INFO, - ("\tUser id range is %d%% full (%d of %d)\n", - num_users * 100 / total_users, num_users, - total_users)); - } - - if (group_hwm != -1) { - int num_groups = group_hwm - server_state.gid_low; - int total_groups = - server_state.gid_high - server_state.gid_low; - - DEBUG(DUMP_INFO, - ("\tGroup id range is %d%% full (%d of %d)\n", - num_groups * 100 / total_groups, num_groups, - total_groups)); - } - - /* Display complete mapping of users and groups to rids */ -} - -struct idmap_methods tdb_idmap_methods = { - tdb_idmap_init, - - tdb_get_sid_from_uid, - tdb_get_sid_from_gid, - - tdb_get_uid_from_sid, - tdb_get_gid_from_sid, - - tdb_idmap_close, - - tdb_idmap_status -}; - -BOOL winbind_idmap_reg_tdb(struct idmap_methods **meth) -{ - *meth = &tdb_idmap_methods; - - return True; -} diff --git a/source4/nsswitch/winbindd_misc.c b/source4/nsswitch/winbindd_misc.c deleted file mode 100644 index b85cd0570d..0000000000 --- a/source4/nsswitch/winbindd_misc.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - miscellaneous other functions - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Bartlett 2002 - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Check the machine account password is valid */ - -enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *state) -{ - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uchar trust_passwd[16]; - int num_retries = 0; - struct cli_state *cli; - DEBUG(3, ("[%5d]: check machine account\n", state->pid)); - - /* Get trust account password */ - - again: - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, NULL)) { - result = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - /* This call does a cli_nt_setup_creds() which implicitly checks - the trust account password. */ - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe\n")); - goto done; - } - - /* There is a race condition between fetching the trust account - password and the periodic machine password change. So it's - possible that the trust account password has been changed on us. - We are returned NT_STATUS_ACCESS_DENIED if this happens. */ - -#define MAX_RETRIES 8 - - if ((num_retries < MAX_RETRIES) && - NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) { - num_retries++; - goto again; - } - - /* Pass back result code - zero for success, other values for - specific failures. */ - - DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ? - "good" : "bad")); - - done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", - state->response.data.auth.nt_status_string)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state - *state) -{ - struct winbindd_domain *domain; - int total_entries = 0, extra_data_len = 0; - char *ted, *extra_data = NULL; - - DEBUG(3, ("[%5d]: list trusted domains\n", state->pid)); - - /* We need to refresh the trusted domain list as the domains may - have changed since we last looked. There may be a sequence - number or something we should use but I haven't found it yet. */ - - if (!init_domain_list()) { - DEBUG(1, ("winbindd_list_trusted_domains: could not " - "refresh trusted domain list\n")); - return WINBINDD_ERROR; - } - - for(domain = domain_list(); domain; domain = domain->next) { - - /* Skip own domain */ - - if (strequal(domain->name, lp_workgroup())) continue; - - /* Add domain to list */ - - total_entries++; - ted = Realloc(extra_data, sizeof(fstring) * - total_entries); - - if (!ted) { - DEBUG(0,("winbindd_list_trusted_domains: failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - return WINBINDD_ERROR; - } else - extra_data = ted; - - memcpy(&extra_data[extra_data_len], domain->name, - strlen(domain->name)); - - extra_data_len += strlen(domain->name); - extra_data[extra_data_len++] = ','; - } - - if (extra_data) { - if (extra_data_len > 1) - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - return WINBINDD_OK; -} - - -enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - char *extra_data = NULL; - - DEBUG(3, ("[%5d]: show sequence\n", state->pid)); - - extra_data = strdup(""); - - /* this makes for a very simple data format, and is easily parsable as well - if that is ever needed */ - for (domain = domain_list(); domain; domain = domain->next) { - char *s; - - domain->methods->sequence_number(domain, &domain->sequence_number); - - if (DOM_SEQUENCE_NONE == (unsigned)domain->sequence_number) { - asprintf(&s,"%s%s : DISCONNECTED\n", extra_data, - domain->name); - } else { - asprintf(&s,"%s%s : %u\n", extra_data, - domain->name, (unsigned)domain->sequence_number); - } - free(extra_data); - extra_data = s; - } - - state->response.extra_data = extra_data; - /* must add one to length to copy the 0 for string termination */ - state->response.length += strlen(extra_data) + 1; - - return WINBINDD_OK; -} - -enum winbindd_result winbindd_ping(struct winbindd_cli_state - *state) -{ - DEBUG(3, ("[%5d]: ping\n", state->pid)); - - return WINBINDD_OK; -} - -/* List various tidbits of information */ - -enum winbindd_result winbindd_info(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request misc info\n", state->pid)); - - state->response.data.info.winbind_separator = *lp_winbind_separator(); - fstrcpy(state->response.data.info.samba_version, VERSION); - - return WINBINDD_OK; -} - -/* Tell the client the current interface version */ - -enum winbindd_result winbindd_interface_version(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request interface version\n", state->pid)); - - state->response.data.interface_version = WINBIND_INTERFACE_VERSION; - - return WINBINDD_OK; -} - -/* What domain are we a member of? */ - -enum winbindd_result winbindd_domain_name(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request domain name\n", state->pid)); - - fstrcpy(state->response.data.domain_name, lp_workgroup()); - - return WINBINDD_OK; -} - -/* What's my name again? */ - -enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request netbios name\n", state->pid)); - - fstrcpy(state->response.data.netbios_name, lp_netbios_name()); - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/winbindd_nss.h b/source4/nsswitch/winbindd_nss.h deleted file mode 100644 index 2c87a77100..0000000000 --- a/source4/nsswitch/winbindd_nss.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) -#endif - -#ifndef _WINBINDD_NTDOM_H -#define _WINBINDD_NTDOM_H - -#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */ -#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */ - -#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */ -#define WINBINDD_DONT_ENV "_NO_WINBINDD" - -/* Update this when you change the interface. */ - -#define WINBIND_INTERFACE_VERSION 7 - -/* Socket commands */ - -enum winbindd_cmd { - - WINBINDD_INTERFACE_VERSION, /* Always a well known value */ - - /* Get users and groups */ - - WINBINDD_GETPWNAM, - WINBINDD_GETPWUID, - WINBINDD_GETGRNAM, - WINBINDD_GETGRGID, - WINBINDD_GETGROUPS, - - /* Enumerate users and groups */ - - WINBINDD_SETPWENT, - WINBINDD_ENDPWENT, - WINBINDD_GETPWENT, - WINBINDD_SETGRENT, - WINBINDD_ENDGRENT, - WINBINDD_GETGRENT, - - /* PAM authenticate and password change */ - - WINBINDD_PAM_AUTH, - WINBINDD_PAM_AUTH_CRAP, - WINBINDD_PAM_CHAUTHTOK, - - /* List various things */ - - WINBINDD_LIST_USERS, /* List w/o rid->id mapping */ - WINBINDD_LIST_GROUPS, /* Ditto */ - WINBINDD_LIST_TRUSTDOM, - - /* SID conversion */ - - WINBINDD_LOOKUPSID, - WINBINDD_LOOKUPNAME, - - /* Lookup functions */ - - WINBINDD_SID_TO_UID, - WINBINDD_SID_TO_GID, - WINBINDD_UID_TO_SID, - WINBINDD_GID_TO_SID, - - /* Miscellaneous other stuff */ - - WINBINDD_CHECK_MACHACC, /* Check machine account pw works */ - WINBINDD_PING, /* Just tell me winbind is running */ - WINBINDD_INFO, /* Various bit of info. Currently just tidbits */ - WINBINDD_DOMAIN_NAME, /* The domain this winbind server is a member of (lp_workgroup()) */ - - WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */ - - /* WINS commands */ - - WINBINDD_WINS_BYIP, - WINBINDD_WINS_BYNAME, - - /* this is like GETGRENT but gives an empty group list */ - WINBINDD_GETGRLST, - - WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ - /* Placeholder for end of cmd list */ - - WINBINDD_NUM_CMDS -}; - -#define WINBIND_PAM_INFO3_NDR 0x0001 -#define WINBIND_PAM_INFO3_TEXT 0x0002 -#define WINBIND_PAM_NTKEY 0x0004 -#define WINBIND_PAM_LMKEY 0x0008 -#define WINBIND_PAM_CONTACT_TRUSTDOM 0x0010 - -/* Winbind request structure */ - -struct winbindd_request { - uint32 length; - enum winbindd_cmd cmd; /* Winbindd command to execute */ - pid_t pid; /* pid of calling process */ - - union { - fstring winsreq; /* WINS request */ - fstring username; /* getpwnam */ - fstring groupname; /* getgrnam */ - uid_t uid; /* getpwuid, uid_to_sid */ - gid_t gid; /* getgrgid, gid_to_sid */ - struct { - /* We deliberatedly don't split into domain/user to - avoid having the client know what the separator - character is. */ - fstring user; - fstring pass; - } auth; /* pam_winbind auth module */ - struct { - unsigned char chal[8]; - fstring user; - fstring domain; - fstring lm_resp; - uint16 lm_resp_len; - fstring nt_resp; - uint16 nt_resp_len; - fstring workstation; - uint32 flags; - } auth_crap; - struct { - fstring user; - fstring oldpass; - fstring newpass; - } chauthtok; /* pam_winbind passwd module */ - fstring sid; /* lookupsid, sid_to_[ug]id */ - struct { - fstring dom_name; /* lookupname */ - fstring name; - } name; - uint32 num_entries; /* getpwent, getgrent */ - } data; - char null_term; -}; - -/* Response values */ - -enum winbindd_result { - WINBINDD_ERROR, - WINBINDD_OK -}; - -/* Winbind response structure */ - -struct winbindd_response { - - /* Header information */ - - uint32 length; /* Length of response */ - enum winbindd_result result; /* Result code */ - - /* Fixed length return data */ - - union { - int interface_version; /* Try to ensure this is always in the same spot... */ - - fstring winsresp; /* WINS response */ - - /* getpwnam, getpwuid */ - - struct winbindd_pw { - fstring pw_name; - fstring pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - fstring pw_gecos; - fstring pw_dir; - fstring pw_shell; - } pw; - - /* getgrnam, getgrgid */ - - struct winbindd_gr { - fstring gr_name; - fstring gr_passwd; - gid_t gr_gid; - int num_gr_mem; - int gr_mem_ofs; /* offset to group membership */ - } gr; - - uint32 num_entries; /* getpwent, getgrent */ - struct winbindd_sid { - fstring sid; /* lookupname, [ug]id_to_sid */ - int type; - } sid; - struct winbindd_name { - fstring dom_name; /* lookupsid */ - fstring name; - int type; - } name; - uid_t uid; /* sid_to_uid */ - gid_t gid; /* sid_to_gid */ - struct winbindd_info { - char winbind_separator; - fstring samba_version; - } info; - fstring domain_name; - fstring netbios_name; - - struct auth_reply { - uint32 nt_status; - fstring nt_status_string; - fstring error_string; - int pam_error; - char nt_session_key[16]; - char first_8_lm_hash[8]; - } auth; - } data; - - /* Variable length return data */ - - void *extra_data; /* getgrnam, getgrgid, getgrent */ -}; - -#endif diff --git a/source4/nsswitch/winbindd_pam.c b/source4/nsswitch/winbindd_pam.c deleted file mode 100644 index 8a0326b42c..0000000000 --- a/source4/nsswitch/winbindd_pam.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - pam auth funcions - - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 2001-2002 - - 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 "winbindd.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - - -static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) -{ - prs_struct ps; - uint32 size; - if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!net_io_user_info3("", info3, &ps, 1, 3)) { - prs_mem_free(&ps); - return NT_STATUS_UNSUCCESSFUL; - } - - size = prs_data_size(&ps); - state->response.extra_data = malloc(size); - if (!state->response.extra_data) { - prs_mem_free(&ps); - return NT_STATUS_NO_MEMORY; - } - prs_copy_all_data_out(state->response.extra_data, &ps); - state->response.length += size; - prs_mem_free(&ps); - return NT_STATUS_OK; -} - -/* Return a password structure from a username. */ - -enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) -{ - NTSTATUS result; - fstring name_domain, name_user; - unsigned char trust_passwd[16]; - time_t last_change_time; - uint32 smb_uid_low; - NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; - uchar chal[8]; - TALLOC_CTX *mem_ctx = NULL; - DATA_BLOB lm_resp; - DATA_BLOB nt_resp; - - /* Ensure null termination */ - state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; - - /* Ensure null termination */ - state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; - - DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, - state->request.data.auth.user)); - - if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) { - DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n")); - result = NT_STATUS_NO_MEMORY; - goto done; - } - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.auth.user, name_domain, - name_user)) { - DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - { - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - generate_random_buffer(chal, 8, False); - SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); - - SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); - - lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); - nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); - } - - /* - * Get the machine account password for our primary domain - */ - - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, &last_change_time)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", lp_workgroup())); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - /* We really don't care what LUID we give the user. */ - - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - ZERO_STRUCT(info3); - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe\n")); - goto done; - } - - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - name_user, name_domain, - lp_netbios_name(), chal, - lm_resp, nt_resp, - &info3); - - uni_group_cache_store_netlogon(mem_ctx, &info3); -done: - - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", - state->request.data.auth.user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - if (mem_ctx) - talloc_destroy(mem_ctx); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* Challenge Response Authentication Protocol */ - -enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) -{ - NTSTATUS result; - unsigned char trust_passwd[16]; - time_t last_change_time; - NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; - TALLOC_CTX *mem_ctx = NULL; - char *user = NULL; - const char *domain = NULL; - const char *contact_domain; - const char *workstation; - - DATA_BLOB lm_resp, nt_resp; - - /* Ensure null termination */ - state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0'; - - /* Ensure null termination */ - state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0'; - - if (!(mem_ctx = talloc_init("winbind pam auth crap for (utf8) %s", state->request.data.auth_crap.user))) { - DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); - result = NT_STATUS_NO_MEMORY; - goto done; - } - - if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - - if (*state->request.data.auth_crap.domain) { - char *dom = NULL; - if (pull_utf8_talloc(mem_ctx, &dom, state->request.data.auth_crap.domain) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - domain = dom; - } else if (lp_winbind_use_default_domain()) { - domain = lp_workgroup(); - } else { - DEBUG(5,("no domain specified with username (%s) - failing auth\n", - user)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, - domain, user)); - - if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) { - contact_domain = domain; - } else { - contact_domain = lp_workgroup(); - } - - if (*state->request.data.auth_crap.workstation) { - char *wrk = NULL; - if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - workstation = wrk; - } else { - workstation = lp_netbios_name(); - } - - if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) - || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { - DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", - state->request.data.auth_crap.lm_resp_len, - state->request.data.auth_crap.nt_resp_len)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); - nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - - /* - * Get the machine account password for the domain to contact. - * This is either our own domain for a workstation, or possibly - * any domain for a PDC with trusted domains. - */ - - if (!secrets_fetch_trust_account_password ( - contact_domain, trust_passwd, &last_change_time)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", contact_domain)); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - ZERO_STRUCT(info3); - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(contact_domain, trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result))); - goto done; - } - - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - user, domain, - workstation, state->request.data.auth_crap.chal, - lm_resp, nt_resp, - &info3); - - if (NT_STATUS_IS_OK(result)) { - uni_group_cache_store_netlogon(mem_ctx, &info3); - if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) { - result = append_info3_as_ndr(mem_ctx, state, &info3); - } - -#if 0 - /* we don't currently do this stuff right */ - /* Doing an assert in a daemon is going to be a pretty bad - idea. - tpot */ - if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) { - SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key)); - memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */); - } - if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) { - SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key)); - memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */); - } -#endif - } - -done: - - state->response.data.auth.nt_status = NT_STATUS_V(result); - push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result)); - push_utf8_fstring(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", - domain, - user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - if (mem_ctx) - talloc_destroy(mem_ctx); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* Change a user password */ - -enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) -{ - NTSTATUS result; - char *oldpass, *newpass; - fstring domain, user; - CLI_POLICY_HND *hnd; - - DEBUG(3, ("[%5d]: pam chauthtok %s\n", state->pid, - state->request.data.chauthtok.user)); - - /* Setup crap */ - - if (state == NULL) - return WINBINDD_ERROR; - - if (!parse_domain_user(state->request.data.chauthtok.user, domain, - user)) { - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Change password */ - - oldpass = state->request.data.chauthtok.oldpass; - newpass = state->request.data.chauthtok.newpass; - - /* Get sam handle */ - - if (!(hnd = cm_get_sam_handle(domain))) { - DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - goto done; - } - - if (!cli_oem_change_password(hnd->cli, user, newpass, oldpass)) { - DEBUG(1, ("password change failed for user %s/%s\n", domain, - user)); - result = NT_STATUS_WRONG_PASSWORD; - } else { - result = NT_STATUS_OK; - } - -done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", - domain, - user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} diff --git a/source4/nsswitch/winbindd_rpc.c b/source4/nsswitch/winbindd_rpc.c deleted file mode 100644 index 9989f27109..0000000000 --- a/source4/nsswitch/winbindd_rpc.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind rpc backend functions - - Copyright (C) Tim Potter 2000-2001,2003 - Copyright (C) Andrew Tridgell 2001 - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - - -/* Query display info for a domain. This returns enough information plus a - bit extra to give an overview of domain users for the User Manager - application. */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol; - BOOL got_dom_pol = False; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - unsigned int i, start_idx, retry; - - DEBUG(3,("rpc: query_user_list\n")); - - *num_entries = 0; - *info = NULL; - - retry = 0; - do { - /* Get sam handle */ - - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - i = start_idx = 0; - do { - TALLOC_CTX *ctx2; - char **dom_users; - uint32 num_dom_users, *dom_rids, j, size = 0xffff; - uint16 acb_mask = ACB_NORMAL; - - if (!(ctx2 = talloc_init("winbindd enum_users"))) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - result = cli_samr_enum_dom_users( - hnd->cli, ctx2, &dom_pol, &start_idx, acb_mask, - size, &dom_users, &dom_rids, &num_dom_users); - - *num_entries += num_dom_users; - - *info = talloc_realloc( - mem_ctx, *info, - (*num_entries) * sizeof(WINBIND_USERINFO)); - - if (!(*info)) { - result = NT_STATUS_NO_MEMORY; - talloc_destroy(ctx2); - goto done; - } - - for (j = 0; j < num_dom_users; i++, j++) { - (*info)[i].acct_name = - talloc_strdup(mem_ctx, dom_users[j]); - (*info)[i].full_name = talloc_strdup(mem_ctx, ""); - (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, dom_rids[j]); - /* For the moment we set the primary group for - every user to be the Domain Users group. - There are serious problems with determining - the actual primary group for large domains. - This should really be made into a 'winbind - force group' smb.conf parameter or - something like that. */ - (*info)[i].group_sid - = rid_to_talloced_sid(domain, - mem_ctx, - DOMAIN_GROUP_RID_USERS); - } - - talloc_destroy(ctx2); - - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); - - done: - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - CLI_POLICY_HND *hnd; - POLICY_HND dom_pol; - NTSTATUS status; - uint32 start = 0; - int retry; - - *num_entries = 0; - *info = NULL; - - DEBUG(3,("rpc: enum_dom_groups\n")); - - retry = 0; - do { - if (!(hnd = cm_get_sam_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; - - status = cli_samr_open_domain(hnd->cli, mem_ctx, - &hnd->pol, des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(status)) - return status; - - do { - struct acct_info *info2 = NULL; - uint32 count = 0; - TALLOC_CTX *mem_ctx2; - - mem_ctx2 = talloc_init("enum_dom_groups[rpc]"); - - /* start is updated by this call. */ - status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol, - &start, - 0xFFFF, /* buffer size? */ - &info2, &count); - - if (!NT_STATUS_IS_OK(status) && - !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - talloc_destroy(mem_ctx2); - break; - } - - (*info) = talloc_realloc(mem_ctx, *info, - sizeof(**info) * ((*num_entries) + count)); - if (! *info) { - talloc_destroy(mem_ctx2); - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - return NT_STATUS_NO_MEMORY; - } - - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); - (*num_entries) += count; - talloc_destroy(mem_ctx2); - } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); - - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return status; -} - -/* List all domain groups */ - -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - CLI_POLICY_HND *hnd; - POLICY_HND dom_pol; - NTSTATUS result; - int retry; - - *num_entries = 0; - *info = NULL; - - retry = 0; - do { - if ( !(hnd = cm_get_sam_handle(domain->name)) ) - return NT_STATUS_UNSUCCESSFUL; - - result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if ( !NT_STATUS_IS_OK(result)) - return result; - - do { - struct acct_info *info2 = NULL; - uint32 count = 0, start = *num_entries; - TALLOC_CTX *mem_ctx2; - - mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]"); - - result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol, - &start, 0xFFFF, &info2, &count); - - if ( !NT_STATUS_IS_OK(result) - && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) - { - talloc_destroy(mem_ctx2); - break; - } - - (*info) = talloc_realloc(mem_ctx, *info, - sizeof(**info) * ((*num_entries) + count)); - if (! *info) { - talloc_destroy(mem_ctx2); - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - return NT_STATUS_NO_MEMORY; - } - - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); - (*num_entries) += count; - talloc_destroy(mem_ctx2); - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); - - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - CLI_POLICY_HND *hnd; - NTSTATUS status; - DOM_SID *sids = NULL; - uint32 *types = NULL; - const char *full_name; - int retry; - - DEBUG(3,("rpc: name_to_sid name=%s\n", name)); - - full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name); - - if (!full_name) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(domain->name))) { - return NT_STATUS_UNSUCCESSFUL; - } - - status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, - &full_name, &sids, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - /* Return rid and type if lookup successful */ - - if (NT_STATUS_IS_OK(status)) { - sid_copy(sid, &sids[0]); - *type = types[0]; - } - - return status; -} - -/* - convert a domain SID to a user or group name -*/ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - CLI_POLICY_HND *hnd; - char **domains; - char **names; - uint32 *types; - NTSTATUS status; - int retry; - - DEBUG(3,("rpc: sid_to_name\n")); - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; - - status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol, - 1, sid, &domains, &names, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (NT_STATUS_IS_OK(status)) { - *type = types[0]; - *name = names[0]; - DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); - - /* Paranoia */ - if (strcasecmp(domain->name, domains[0]) != 0) { - DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0])); - return NT_STATUS_UNSUCCESSFUL; - } - } - return status; -} - -/* Lookup user information from a rid or username. */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *user_info) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol, user_pol; - BOOL got_dom_pol = False, got_user_pol = False; - SAM_USERINFO_CTR *ctr; - int retry; - fstring sid_string; - uint32 user_rid; - - DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid))); - if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { - goto done; - } - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Get user handle */ - result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_user_pol = True; - - /* Get user info */ - result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, - 0x15, &ctr); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - got_user_pol = False; - - user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid); - user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid); - user_info->acct_name = unistr2_tdup(mem_ctx, - &ctr->info.id21->uni_user_name); - user_info->full_name = unistr2_tdup(mem_ctx, - &ctr->info.id21->uni_full_name); - - done: - /* Clean up policy handles */ - if (got_user_pol) - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* Lookup groups a user is a member of. I wish Unix had a call like this! */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol, user_pol; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - BOOL got_dom_pol = False, got_user_pol = False; - DOM_GID *user_groups; - unsigned int i; - unsigned int retry; - fstring sid_string; - uint32 user_rid; - - DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid))); - - *num_groups = 0; - - /* First try cached universal groups from logon */ - *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups); - if((*num_groups > 0) && *user_gids) { - return NT_STATUS_OK; - } else { - *user_gids = NULL; - *num_groups = 0; - } - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - - if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { - goto done; - } - - /* Get user handle */ - result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, - des_access, user_rid, &user_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_user_pol = True; - - /* Query user rids */ - result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, - num_groups, &user_groups); - - if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) - goto done; - - (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); - if (!(*user_gids)) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - for (i=0;i<(*num_groups);i++) { - (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); - } - - done: - /* Clean up policy handles */ - if (got_user_pol) - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - - -/* Lookup group membership given a rid. */ -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 i, total_names = 0; - POLICY_HND dom_pol, group_pol; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - BOOL got_dom_pol = False, got_group_pol = False; - uint32 *rid_mem = NULL; - uint32 group_rid; - int retry; - unsigned int j; - fstring sid_string; - - DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); - - if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { - goto done; - } - - *num_names = 0; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Get group handle */ - - result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, - des_access, group_rid, &group_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_group_pol = True; - - /* Step #1: Get a list of user rids that are the members of the - group. */ - - result = cli_samr_query_groupmem(hnd->cli, mem_ctx, - &group_pol, num_names, &rid_mem, - name_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Step #2: Convert list of rids into list of usernames. Do this - in bunches of ~1000 to avoid crashing NT4. It looks like there - is a buffer overflow or something like that lurking around - somewhere. */ - -#define MAX_LOOKUP_RIDS 900 - - *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); - *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); - *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); - - for (j=0;j<(*num_names);j++) { - (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); - } - - if (!*names || !*name_types) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { - int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); - uint32 tmp_num_names = 0; - char **tmp_names = NULL; - uint32 *tmp_types = NULL; - - /* Lookup a chunk of rids */ - - result = cli_samr_lookup_rids(hnd->cli, mem_ctx, - &dom_pol, 1000, /* flags */ - num_lookup_rids, - &rid_mem[i], - &tmp_num_names, - &tmp_names, &tmp_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Copy result into array. The talloc system will take - care of freeing the temporary arrays later on. */ - - memcpy(&(*names)[i], tmp_names, sizeof(char *) * - tmp_num_names); - - memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * - tmp_num_names); - - total_names += tmp_num_names; - } - - *num_names = total_names; - - done: - if (got_group_pol) - cli_samr_close(hnd->cli, mem_ctx, &group_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - TALLOC_CTX *mem_ctx; - CLI_POLICY_HND *hnd; - SAM_UNK_CTR ctr; - uint16 switch_value = 2; - NTSTATUS result; - uint32 seqnum = DOM_SEQUENCE_NONE; - POLICY_HND dom_pol; - BOOL got_dom_pol = False; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - int retry; - - DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); - - *seq = DOM_SEQUENCE_NONE; - - if (!(mem_ctx = talloc_init("sequence_number[rpc]"))) - return NT_STATUS_NO_MEMORY; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Query domain info */ - - result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol, - switch_value, &ctr); - - if (NT_STATUS_IS_OK(result)) { - seqnum = ctr.info.inf2.seq_num; - DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum )); - } else { - DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n", - (unsigned)seqnum, domain->name )); - } - - done: - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - talloc_destroy(mem_ctx); - - *seq = seqnum; - - return result; -} - -/* get a list of trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 enum_ctx = 0; - int retry; - - DEBUG(3,("rpc: trusted_domains\n")); - - *num_domains = 0; - *alt_names = NULL; - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) - goto done; - - result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx, - &hnd->pol, &enum_ctx, - num_domains, names, dom_sids); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - -done: - return result; -} - -/* find the domain sid for a domain */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *mem_ctx; - CLI_POLICY_HND *hnd; - fstring level5_dom; - int retry; - - DEBUG(3,("rpc: domain_sid\n")); - - if (!(mem_ctx = talloc_init("domain_sid[rpc]"))) - return NT_STATUS_NO_MEMORY; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_lsa_handle(domain->name))) - goto done; - - status = cli_lsa_query_info_policy(hnd->cli, mem_ctx, - &hnd->pol, 0x05, level5_dom, sid); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - -done: - talloc_destroy(mem_ctx); - return status; -} - -/* find alternate names list for the domain - none for rpc */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - return NT_STATUS_OK; -} - - -/* the rpc backend methods are exposed via this structure */ -struct winbindd_methods msrpc_methods = { - False, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; diff --git a/source4/nsswitch/winbindd_sid.c b/source4/nsswitch/winbindd_sid.c deleted file mode 100644 index 6ab2eaa646..0000000000 --- a/source4/nsswitch/winbindd_sid.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - sid related functions - - Copyright (C) Tim Potter 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Convert a string */ - -enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state) -{ - extern DOM_SID global_sid_Builtin; - enum SID_NAME_USE type; - DOM_SID sid, tmp_sid; - uint32 rid; - fstring name; - fstring dom_name; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid, - state->request.data.sid)); - - /* Lookup sid from PDC using lsa_lookup_sids() */ - - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(5, ("%s not a SID\n", state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Don't look up BUILTIN sids */ - - sid_copy(&tmp_sid, &sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(&tmp_sid, &global_sid_Builtin)) { - return WINBINDD_ERROR; - } - - /* Lookup the sid */ - - if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) { - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.dom_name, dom_name); - fstrcpy(state->response.data.name.name, name); - - state->response.data.name.type = type; - - return WINBINDD_OK; -} - - -/** - * Look up the SID for a qualified name. - **/ -enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) -{ - enum SID_NAME_USE type; - fstring sid_str; - char *name_domain, *name_user; - DOM_SID sid; - struct winbindd_domain *domain; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0'; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0'; - - DEBUG(3, ("[%5d]: lookupname %s%s%s\n", state->pid, - state->request.data.name.dom_name, - lp_winbind_separator(), - state->request.data.name.name)); - - name_domain = state->request.data.name.dom_name; - name_user = state->request.data.name.name; - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", - name_domain)); - return WINBINDD_ERROR; - } - - /* Lookup name from PDC using lsa_lookup_names() */ - if (!winbindd_lookup_sid_by_name(domain, name_user, &sid, &type)) { - return WINBINDD_ERROR; - } - - sid_to_string(sid_str, &sid); - fstrcpy(state->response.data.sid.sid, sid_str); - state->response.data.sid.type = type; - - return WINBINDD_OK; -} - -/* Convert a sid to a uid. We assume we only have one rid attached to the - sid. */ - -enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid, - state->request.data.sid)); - - /* Split sid into domain sid and user rid */ - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Find uid for this sid and return it */ - if (!winbindd_idmap_get_uid_from_sid(&sid, &state->response.data.uid)) { - DEBUG(1, ("Could not get uid for sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - return WINBINDD_OK; -} - -/* Convert a sid to a gid. We assume we only have one rid attached to the - sid.*/ - -enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid, - state->request.data.sid)); - - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not cvt string to sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Find gid for this sid and return it */ - if (!winbindd_idmap_get_gid_from_sid(&sid, &state->response.data.gid)) { - DEBUG(1, ("Could not get gid for sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - return WINBINDD_OK; -} - -/* Convert a uid to a sid */ - -enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Bug out if the uid isn't in the winbind range */ - - if ((state->request.data.uid < server_state.uid_low ) || - (state->request.data.uid > server_state.uid_high)) { - return WINBINDD_ERROR; - } - - DEBUG(3, ("[%5d]: uid to sid %d\n", state->pid, - state->request.data.uid)); - - /* Lookup rid for this uid */ - if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, &sid)) { - DEBUG(1, ("Could not convert uid %d to rid\n", - state->request.data.uid)); - return WINBINDD_ERROR; - } - - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_USER; - - return WINBINDD_OK; -} - -/* Convert a gid to a sid */ - -enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Bug out if the gid isn't in the winbind range */ - - if ((state->request.data.gid < server_state.gid_low) || - (state->request.data.gid > server_state.gid_high)) { - return WINBINDD_ERROR; - } - - DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid, - state->request.data.gid)); - - /* Lookup sid for this uid */ - if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &sid)) { - DEBUG(1, ("Could not convert gid %d to sid\n", - state->request.data.gid)); - return WINBINDD_ERROR; - } - - /* Construct sid and return it */ - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_DOM_GRP; - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/winbindd_user.c b/source4/nsswitch/winbindd_user.c deleted file mode 100644 index ee05543d30..0000000000 --- a/source4/nsswitch/winbindd_user.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - user related functions - - Copyright (C) Tim Potter 2000 - Copyright (C) Jeremy Allison 2001. - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Fill a pwent structure with information we have obtained */ - -static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, - DOM_SID *user_sid, DOM_SID *group_sid, - char *full_name, struct winbindd_pw *pw) -{ - extern userdom_struct current_user_info; - fstring output_username; - pstring homedir; - fstring sid_string; - - if (!pw || !dom_name || !user_name) - return False; - - /* Resolve the uid number */ - - if (!winbindd_idmap_get_uid_from_sid(user_sid, - &pw->pw_uid)) { - DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); - return False; - } - - /* Resolve the gid number */ - - if (!winbindd_idmap_get_gid_from_sid(group_sid, - &pw->pw_gid)) { - DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); - return False; - } - - /* Username */ - - fill_domain_username(output_username, dom_name, user_name); - - safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); - - /* Full name (gecos) */ - - safe_strcpy(pw->pw_gecos, full_name, sizeof(pw->pw_gecos) - 1); - - /* Home directory and shell - use template config parameters. The - defaults are /tmp for the home directory and /bin/false for - shell. */ - - /* The substitution of %U and %D in the 'template homedir' is done - by lp_string() calling standard_sub_basic(). */ - - fstrcpy(current_user_info.smb_name, user_name); - sub_set_smb_name(user_name); - fstrcpy(current_user_info.domain, dom_name); - - pstrcpy(homedir, lp_template_homedir()); - - safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1); - - safe_strcpy(pw->pw_shell, lp_template_shell(), - sizeof(pw->pw_shell) - 1); - - /* Password - set to "x" as we can't generate anything useful here. - Authentication can be done using the pam_winbind module. */ - - safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1); - - return True; -} - -/* Return a password structure from a username. */ - -enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) -{ - WINBIND_USERINFO user_info; - DOM_SID user_sid; - NTSTATUS status; - fstring name_domain, name_user; - enum SID_NAME_USE name_type; - struct winbindd_domain *domain; - TALLOC_CTX *mem_ctx; - - /* Ensure null termination */ - state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - - DEBUG(3, ("[%5d]: getpwnam %s\n", state->pid, - state->request.data.username)); - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) - return WINBINDD_ERROR; - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(5, ("no such domain: %s\n", name_domain)); - return WINBINDD_ERROR; - } - - /* Get rid and name type from name */ - - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) { - DEBUG(1, ("user '%s' does not exist\n", name_user)); - return WINBINDD_ERROR; - } - - if (name_type != SID_NAME_USER) { - DEBUG(1, ("name '%s' is not a user name: %d\n", name_user, - name_type)); - return WINBINDD_ERROR; - } - - /* Get some user info. Split the user rid from the sid obtained - from the winbind_lookup_by_name() call and use it in a - winbind_lookup_userinfo() */ - - if (!(mem_ctx = talloc_init("winbindd_getpwnam([%s]\\[%s])", - name_domain, name_user))) { - DEBUG(1, ("out of memory\n")); - return WINBINDD_ERROR; - } - - status = domain->methods->query_user(domain, mem_ctx, &user_sid, - &user_info); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("error getting user info for user '[%s]\\[%s]'\n", - name_domain, name_user)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Now take all this information and fill in a passwd structure */ - if (!winbindd_fill_pwent(name_domain, name_user, - user_info.user_sid, user_info.group_sid, - user_info.full_name, - &state->response.data.pw)) { - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - talloc_destroy(mem_ctx); - - return WINBINDD_OK; -} - -/* Return a password structure given a uid number */ - -enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) -{ - DOM_SID user_sid; - struct winbindd_domain *domain; - fstring dom_name; - fstring user_name; - enum SID_NAME_USE name_type; - WINBIND_USERINFO user_info; - gid_t gid; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - - /* Bug out if the uid isn't in the winbind range */ - - if ((state->request.data.uid < server_state.uid_low ) || - (state->request.data.uid > server_state.uid_high)) - return WINBINDD_ERROR; - - DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid, - state->request.data.uid)); - - /* Get rid from uid */ - - if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, - &user_sid)) { - DEBUG(1, ("could not convert uid %d to SID\n", - state->request.data.uid)); - return WINBINDD_ERROR; - } - - /* Get name and name type from rid */ - - if (!winbindd_lookup_name_by_sid(&user_sid, dom_name, user_name, &name_type)) { - fstring temp; - - sid_to_string(temp, &user_sid); - DEBUG(1, ("could not lookup sid %s\n", temp)); - return WINBINDD_ERROR; - } - - domain = find_domain_from_sid(&user_sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return WINBINDD_ERROR; - } - - /* Get some user info */ - - if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)", - state->request.data.uid))) { - - DEBUG(1, ("out of memory\n")); - return WINBINDD_ERROR; - } - - status = domain->methods->query_user(domain, mem_ctx, &user_sid, - &user_info); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("error getting user info for user '%s'\n", - user_name)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Resolve gid number */ - - if (!winbindd_idmap_get_gid_from_sid(user_info.group_sid, &gid)) { - DEBUG(1, ("error getting group id for user %s\n", user_name)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Fill in password structure */ - - if (!winbindd_fill_pwent(domain->name, user_name, user_info.user_sid, - user_info.group_sid, - user_info.full_name, &state->response.data.pw)) { - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - talloc_destroy(mem_ctx); - - return WINBINDD_OK; -} - -/* - * set/get/endpwent functions - */ - -/* Rewind file pointer for ntdom passwd database */ - -enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - - DEBUG(3, ("[%5d]: setpwent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_users()) - return WINBINDD_ERROR; - - /* Free old static data if it exists */ - - if (state->getpwent_state != NULL) { - free_getent_state(state->getpwent_state); - state->getpwent_state = NULL; - } - - /* Create sam pipes for each domain we know about */ - - for(domain = domain_list(); domain != NULL; domain = domain->next) { - struct getent_state *domain_state; - - /* Create a state record for this domain */ - - if ((domain_state = (struct getent_state *) - malloc(sizeof(struct getent_state))) == NULL) - return WINBINDD_ERROR; - - ZERO_STRUCTP(domain_state); - - fstrcpy(domain_state->domain_name, domain->name); - - /* Add to list of open domains */ - - DLIST_ADD(state->getpwent_state, domain_state); - } - - return WINBINDD_OK; -} - -/* Close file pointer to ntdom passwd database */ - -enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5d]: endpwent\n", state->pid)); - - free_getent_state(state->getpwent_state); - state->getpwent_state = NULL; - - return WINBINDD_OK; -} - -/* Get partial list of domain users for a domain. We fill in the sam_entries, - and num_sam_entries fields with domain user information. The dispinfo_ndx - field is incremented to the index of the next user to fetch. Return True if - some users were returned, False otherwise. */ - -#define MAX_FETCH_SAM_ENTRIES 100 - -static BOOL get_sam_user_entries(struct getent_state *ent) -{ - NTSTATUS status; - uint32 num_entries; - WINBIND_USERINFO *info; - struct getpwent_user *name_list = NULL; - BOOL result = False; - TALLOC_CTX *mem_ctx; - struct winbindd_domain *domain; - struct winbindd_methods *methods; - unsigned int i; - - if (ent->num_sam_entries) - return False; - - if (!(mem_ctx = talloc_init("get_sam_user_entries(%s)", - ent->domain_name))) - return False; - - if (!(domain = find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("no such domain %s in get_sam_user_entries\n", - ent->domain_name)); - return False; - } - - methods = domain->methods; - - /* Free any existing user info */ - - SAFE_FREE(ent->sam_entries); - ent->num_sam_entries = 0; - - /* Call query_user_list to get a list of usernames and user rids */ - - num_entries = 0; - - status = methods->query_user_list(domain, mem_ctx, &num_entries, - &info); - - if (num_entries) { - struct getpwent_user *tnl; - - tnl = (struct getpwent_user *)Realloc(name_list, - sizeof(struct getpwent_user) * - (ent->num_sam_entries + - num_entries)); - - if (!tnl) { - DEBUG(0,("get_sam_user_entries realloc failed.\n")); - SAFE_FREE(name_list); - goto done; - } else - name_list = tnl; - } - - for (i = 0; i < num_entries; i++) { - /* Store account name and gecos */ - if (!info[i].acct_name) { - fstrcpy(name_list[ent->num_sam_entries + i].name, ""); - } else { - fstrcpy(name_list[ent->num_sam_entries + i].name, - info[i].acct_name); - } - if (!info[i].full_name) { - fstrcpy(name_list[ent->num_sam_entries + i].gecos, ""); - } else { - fstrcpy(name_list[ent->num_sam_entries + i].gecos, - info[i].full_name); - } - - /* User and group ids */ - sid_copy(&name_list[ent->num_sam_entries+i].user_sid, info[i].user_sid); - sid_copy(&name_list[ent->num_sam_entries+i].group_sid, info[i].group_sid); - } - - ent->num_sam_entries += num_entries; - - /* Fill in remaining fields */ - - ent->sam_entries = name_list; - ent->sam_entry_index = 0; - result = ent->num_sam_entries > 0; - - done: - - talloc_destroy(mem_ctx); - - return result; -} - -/* Fetch next passwd entry from ntdom database */ - -#define MAX_GETPWENT_USERS 500 - -enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) -{ - struct getent_state *ent; - struct winbindd_pw *user_list; - int num_users, user_list_ndx = 0, i; - - DEBUG(3, ("[%5d]: getpwent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_users()) - return WINBINDD_ERROR; - - /* Allocate space for returning a chunk of users */ - - num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries); - - if ((state->response.extra_data = - malloc(num_users * sizeof(struct winbindd_pw))) == NULL) - return WINBINDD_ERROR; - - memset(state->response.extra_data, 0, num_users * - sizeof(struct winbindd_pw)); - - user_list = (struct winbindd_pw *)state->response.extra_data; - - if (!(ent = state->getpwent_state)) - return WINBINDD_ERROR; - - /* Start sending back users */ - - for (i = 0; i < num_users; i++) { - struct getpwent_user *name_list = NULL; - fstring domain_user_name; - uint32 result; - - /* Do we need to fetch another chunk of users? */ - - if (ent->num_sam_entries == ent->sam_entry_index) { - - while(ent && !get_sam_user_entries(ent)) { - struct getent_state *next_ent; - - /* Free state information for this domain */ - - SAFE_FREE(ent->sam_entries); - - next_ent = ent->next; - DLIST_REMOVE(state->getpwent_state, ent); - - SAFE_FREE(ent); - ent = next_ent; - } - - /* No more domains */ - - if (!ent) - break; - } - - name_list = ent->sam_entries; - - /* Skip machine accounts */ - - if (name_list[ent->sam_entry_index]. - name[strlen(name_list[ent->sam_entry_index].name) - 1] - == '$') { - ent->sam_entry_index++; - continue; - } - - /* Lookup user info */ - - result = winbindd_fill_pwent( - ent->domain_name, - name_list[ent->sam_entry_index].name, - &name_list[ent->sam_entry_index].user_sid, - &name_list[ent->sam_entry_index].group_sid, - name_list[ent->sam_entry_index].gecos, - &user_list[user_list_ndx]); - - ent->sam_entry_index++; - - /* Add user to return list */ - - if (result) { - - user_list_ndx++; - state->response.data.num_entries++; - state->response.length += - sizeof(struct winbindd_pw); - - } else - DEBUG(1, ("could not lookup domain user %s\n", - domain_user_name)); - } - - /* Out of domains */ - - return (user_list_ndx > 0) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* List domain users without mapping to unix ids */ - -enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - WINBIND_USERINFO *info; - uint32 num_entries = 0, total_entries = 0; - char *ted, *extra_data = NULL; - int extra_data_len = 0; - TALLOC_CTX *mem_ctx; - enum winbindd_result rv = WINBINDD_ERROR; - - DEBUG(3, ("[%5d]: list users\n", state->pid)); - - if (!(mem_ctx = talloc_init("winbindd_list_users"))) - return WINBINDD_ERROR; - - /* Enumerate over trusted domains */ - - for (domain = domain_list(); domain; domain = domain->next) { - NTSTATUS status; - struct winbindd_methods *methods; - unsigned int i; - - methods = domain->methods; - - /* Query display info */ - status = methods->query_user_list(domain, mem_ctx, - &num_entries, &info); - - if (num_entries == 0) - continue; - - /* Allocate some memory for extra data */ - total_entries += num_entries; - - ted = Realloc(extra_data, sizeof(fstring) * total_entries); - - if (!ted) { - DEBUG(0,("failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - goto done; - } else - extra_data = ted; - - /* Pack user list into extra data fields */ - - for (i = 0; i < num_entries; i++) { - fstring acct_name, name; - - if (!info[i].acct_name) { - fstrcpy(acct_name, ""); - } else { - fstrcpy(acct_name, info[i].acct_name); - } - - fill_domain_username(name, domain->name, acct_name); - - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } - } - - /* Assign extra_data fields in response structure */ - - if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - /* No domains responded but that's still OK so don't return an - error. */ - - rv = WINBINDD_OK; - - done: - - talloc_destroy(mem_ctx); - - return rv; -} diff --git a/source4/nsswitch/winbindd_util.c b/source4/nsswitch/winbindd_util.c deleted file mode 100644 index 7ccf032041..0000000000 --- a/source4/nsswitch/winbindd_util.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000-2001 - Copyright (C) 2001 by Martin Pool <mbp@samba.org> - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/** - * @file winbindd_util.c - * - * Winbind daemon for NT domain authentication nss module. - **/ - - -/** - * Used to clobber name fields that have an undefined value. - * - * Correct code should never look at a field that has this value. - **/ - -static const fstring name_deadbeef = "<deadbeef>"; - -/* The list of trusted domains. Note that the list can be deleted and - recreated using the init_domain_list() function so pointers to - individual winbindd_domain structures cannot be made. Keep a copy of - the domain name instead. */ - -static struct winbindd_domain *_domain_list; - -struct winbindd_domain *domain_list(void) -{ - /* Initialise list */ - - if (!_domain_list) - init_domain_list(); - - return _domain_list; -} - -/* Free all entries in the trusted domain list */ - -void free_domain_list(void) -{ - struct winbindd_domain *domain = _domain_list; - - while(domain) { - struct winbindd_domain *next = domain->next; - - DLIST_REMOVE(_domain_list, domain); - SAFE_FREE(domain); - domain = next; - } -} - - -/* Add a trusted domain to our list of domains */ -static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, - struct winbindd_methods *methods, - DOM_SID *sid) -{ - struct winbindd_domain *domain; - - /* We can't call domain_list() as this function is called from - init_domain_list() and we'll get stuck in a loop. */ - for (domain = _domain_list; domain; domain = domain->next) { - if (strcasecmp(domain_name, domain->name) == 0 || - strcasecmp(domain_name, domain->alt_name) == 0) { - return domain; - } - if (alt_name && *alt_name) { - if (strcasecmp(alt_name, domain->name) == 0 || - strcasecmp(alt_name, domain->alt_name) == 0) { - return domain; - } - } - } - - /* Create new domain entry */ - - if ((domain = (struct winbindd_domain *) - malloc(sizeof(*domain))) == NULL) - return NULL; - - /* Fill in fields */ - - ZERO_STRUCTP(domain); - - /* prioritise the short name */ - if (strchr_m(domain_name, '.') && alt_name && *alt_name) { - fstrcpy(domain->name, alt_name); - fstrcpy(domain->alt_name, domain_name); - } else { - fstrcpy(domain->name, domain_name); - if (alt_name) { - fstrcpy(domain->alt_name, alt_name); - } - } - - domain->methods = methods; - domain->sequence_number = DOM_SEQUENCE_NONE; - domain->last_seq_check = 0; - if (sid) { - sid_copy(&domain->sid, sid); - } - - /* see if this is a native mode win2k domain, but only for our own domain */ - - if ( strequal( lp_workgroup(), domain_name) ) { - domain->native_mode = cm_check_for_native_mode_win2k( domain_name ); - DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain_name, - domain->native_mode ? "native" : "mixed" )); - } - - /* Link to domain list */ - DLIST_ADD(_domain_list, domain); - - DEBUG(1,("Added domain %s %s %s\n", - domain->name, domain->alt_name, - sid?sid_string_static(&domain->sid):"")); - - return domain; -} - - -/* - rescan our domains looking for new trusted domains - */ -void rescan_trusted_domains(BOOL force) -{ - struct winbindd_domain *domain; - TALLOC_CTX *mem_ctx; - static time_t last_scan; - time_t t = time(NULL); - - /* trusted domains might be disabled */ - if (!lp_allow_trusted_domains()) { - return; - } - - /* Only rescan every few minutes but force if necessary */ - - if (((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) && !force) - return; - - last_scan = t; - - DEBUG(1, ("scanning trusted domain list\n")); - - if (!(mem_ctx = talloc_init("init_domain_list"))) - return; - - for (domain = _domain_list; domain; domain = domain->next) { - NTSTATUS result; - char **names; - char **alt_names; - int num_domains = 0; - DOM_SID *dom_sids; - int i; - - result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains, - &names, &alt_names, &dom_sids); - if (!NT_STATUS_IS_OK(result)) { - continue; - } - - /* Add each domain to the trusted domain list. Each domain inherits - the access methods of its parent */ - for(i = 0; i < num_domains; i++) { - DEBUG(10,("Found domain %s\n", names[i])); - add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); - - /* store trusted domain in the cache */ - trustdom_cache_store(mem_ctx, names[i], alt_names ? alt_names[i] : NULL, - &dom_sids[i], t + WINBINDD_RESCAN_FREQ); - } - } - - talloc_destroy(mem_ctx); -} - -/* Look up global info for the winbind daemon */ -BOOL init_domain_list(void) -{ - extern struct winbindd_methods cache_methods; - struct winbindd_domain *domain; - - /* Free existing list */ - free_domain_list(); - - /* Add ourselves as the first entry */ - domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL); - if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { - DEBUG(1, ("Could not fetch sid for our domain %s\n", - domain->name)); - return False; - } - - /* get any alternate name for the primary domain */ - cache_methods.alternate_name(domain); - - /* do an initial scan for trusted domains */ - rescan_trusted_domains(True); - - return True; -} - -/* Given a domain name, return the struct winbindd domain info for it - if it is actually working. */ - -struct winbindd_domain *find_domain_from_name(const char *domain_name) -{ - struct winbindd_domain *domain; - - /* Search through list */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - if (strequal(domain_name, domain->name) || - (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) - return domain; - } - - /* Not found */ - - return NULL; -} - -/* Given a domain sid, return the struct winbindd domain info for it */ - -struct winbindd_domain *find_domain_from_sid(DOM_SID *sid) -{ - struct winbindd_domain *domain; - - /* Search through list */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - if (sid_compare_domain(sid, &domain->sid) == 0) - return domain; - } - - /* Not found */ - - return NULL; -} - -/* Lookup a sid in a domain from a name */ - -BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, - const char *name, DOM_SID *sid, - enum SID_NAME_USE *type) -{ - NTSTATUS result; - TALLOC_CTX *mem_ctx; - /* Don't bother with machine accounts */ - - if (name[strlen(name) - 1] == '$') - return False; - - mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); - if (!mem_ctx) - return False; - - /* Lookup name */ - result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type); - - talloc_destroy(mem_ctx); - - /* Return rid and type if lookup successful */ - if (!NT_STATUS_IS_OK(result)) { - *type = SID_NAME_UNKNOWN; - } - - return NT_STATUS_IS_OK(result); -} - -/** - * @brief Lookup a name in a domain from a sid. - * - * @param sid Security ID you want to look up. - * - * @param name On success, set to the name corresponding to @p sid. - * - * @param dom_name On success, set to the 'domain name' corresponding to @p sid. - * - * @param type On success, contains the type of name: alias, group or - * user. - * - * @retval True if the name exists, in which case @p name and @p type - * are set, otherwise False. - **/ -BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, - fstring dom_name, - fstring name, - enum SID_NAME_USE *type) -{ - char *names; - NTSTATUS result; - TALLOC_CTX *mem_ctx; - BOOL rv = False; - struct winbindd_domain *domain; - - domain = find_domain_from_sid(sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return False; - } - - /* Lookup name */ - - if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid"))) - return False; - - result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type); - - /* Return name and type if successful */ - - if ((rv = NT_STATUS_IS_OK(result))) { - fstrcpy(dom_name, domain->name); - fstrcpy(name, names); - } else { - *type = SID_NAME_UNKNOWN; - fstrcpy(name, name_deadbeef); - } - - talloc_destroy(mem_ctx); - - return rv; -} - - -/* Free state information held for {set,get,end}{pw,gr}ent() functions */ - -void free_getent_state(struct getent_state *state) -{ - struct getent_state *temp; - - /* Iterate over state list */ - - temp = state; - - while(temp != NULL) { - struct getent_state *next; - - /* Free sam entries then list entry */ - - SAFE_FREE(state->sam_entries); - DLIST_REMOVE(state, state); - next = temp->next; - - SAFE_FREE(temp); - temp = next; - } -} - -/* Parse winbindd related parameters */ - -BOOL winbindd_param_init(void) -{ - /* Parse winbind uid and winbind_gid parameters */ - - if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) { - DEBUG(0, ("winbind uid range missing or invalid\n")); - return False; - } - - if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) { - DEBUG(0, ("winbind gid range missing or invalid\n")); - return False; - } - - return True; -} - -/* Check if a domain is present in a comma-separated list of domains */ - -BOOL check_domain_env(char *domain_env, char *domain) -{ - fstring name; - const char *tmp = domain_env; - - while(next_token(&tmp, name, ",", sizeof(fstring))) { - if (strequal(name, domain)) - return True; - } - - return False; -} - -/* Parse a string of the form DOMAIN/user into a domain and a user */ - -BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) -{ - char *p = strchr(domuser,*lp_winbind_separator()); - - if (!(p || lp_winbind_use_default_domain())) - return False; - - if(!p && lp_winbind_use_default_domain()) { - fstrcpy(user, domuser); - fstrcpy(domain, lp_workgroup()); - } else { - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - } - strupper(domain); - return True; -} - -/* - Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and - 'winbind separator' options. - This means: - - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is - lp_workgroup - -*/ -void fill_domain_username(fstring name, const char *domain, const char *user) -{ - if(lp_winbind_use_default_domain() && - !strcmp(lp_workgroup(), domain)) { - strlcpy(name, user, sizeof(fstring)); - } else { - slprintf(name, sizeof(fstring) - 1, "%s%s%s", - domain, lp_winbind_separator(), - user); - } -} - -/* - * Winbindd socket accessor functions - */ - -/* Open the winbindd socket */ - -static int _winbindd_socket = -1; - -int open_winbindd_socket(void) -{ - if (_winbindd_socket == -1) { - _winbindd_socket = create_pipe_sock( - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755); - DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", - _winbindd_socket)); - } - - return _winbindd_socket; -} - -/* Close the winbindd socket */ - -void close_winbindd_socket(void) -{ - if (_winbindd_socket != -1) { - DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", - _winbindd_socket)); - close(_winbindd_socket); - _winbindd_socket = -1; - } -} - -/* - * Client list accessor functions - */ - -static struct winbindd_cli_state *_client_list; -static int _num_clients; - -/* Return list of all connected clients */ - -struct winbindd_cli_state *winbindd_client_list(void) -{ - return _client_list; -} - -/* Add a connection to the list */ - -void winbindd_add_client(struct winbindd_cli_state *cli) -{ - DLIST_ADD(_client_list, cli); - _num_clients++; -} - -/* Remove a client from the list */ - -void winbindd_remove_client(struct winbindd_cli_state *cli) -{ - DLIST_REMOVE(_client_list, cli); - _num_clients--; -} - -/* Close all open clients */ - -void winbindd_kill_all_clients(void) -{ - struct winbindd_cli_state *cl = winbindd_client_list(); - - DEBUG(10, ("winbindd_kill_all_clients: going postal\n")); - - while (cl) { - struct winbindd_cli_state *next; - - next = cl->next; - winbindd_remove_client(cl); - cl = next; - } -} - -/* Return number of open clients */ - -int winbindd_num_clients(void) -{ - return _num_clients; -} - -/* Help with RID -> SID conversion */ - -DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 rid) -{ - DOM_SID *sid; - sid = talloc(mem_ctx, sizeof(*sid)); - if (!sid) { - smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n"); - } - sid_copy(sid, &domain->sid); - sid_append_rid(sid, rid); - return sid; -} - diff --git a/source4/nsswitch/winbindd_wins.c b/source4/nsswitch/winbindd_wins.c deleted file mode 100644 index 8ddd5dc10d..0000000000 --- a/source4/nsswitch/winbindd_wins.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - WINS related functions - - Copyright (C) Andrew Tridgell 1999 - Copyright (C) Herb Lewis 2002 - - 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 "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Use our own create socket code so we don't recurse.... */ - -static int wins_lookup_open_socket_in(void) -{ - struct sockaddr_in sock; - int val=1; - int res; - - memset((char *)&sock,'\0',sizeof(sock)); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = 0; - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); - res = socket(AF_INET, SOCK_DGRAM, 0); - if (res == -1) - return -1; - - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif /* SO_REUSEPORT */ - - /* now we've got a socket - we need to bind it */ - - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { - close(res); - return(-1); - } - - set_socket_options(res,"SO_BROADCAST"); - - return res; -} - - -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - -static struct in_addr *lookup_byname_backend(const char *name, int *count) -{ - int fd; - struct in_addr *ret = NULL; - int j, flags = 0; - - *count = 0; - - /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { - return ret; - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) { - return NULL; - } - - /* uggh, we have to broadcast to each interface in turn */ - for (j=iface_count() - 1; - j >= 0; - j--) { - struct in_addr *bcast = iface_n_bcast(j); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; - } - - close(fd); - return ret; -} - -/* Get hostname from IP */ - -enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state) -{ - fstring response; - int i, count, maxlen, size; - struct node_status *status; - - /* Ensure null termination */ - state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - - DEBUG(3, ("[%5d]: wins_byip %s\n", state->pid, - state->request.data.winsreq)); - - *response = '\0'; - maxlen = sizeof(response) - 1; - - if ((status = lookup_byaddr_backend(state->request.data.winsreq, &count))){ - size = strlen(state->request.data.winsreq); - if (size > maxlen) { - SAFE_FREE(status); - return WINBINDD_ERROR; - } - safe_strcat(response,state->request.data.winsreq,maxlen); - safe_strcat(response,"\t",maxlen); - for (i = 0; i < count; i++) { - /* ignore group names */ - if (status[i].flags & 0x80) continue; - if (status[i].type == 0x20) { - size = sizeof(status[i].name) + strlen(response); - if (size > maxlen) { - SAFE_FREE(status); - return WINBINDD_ERROR; - } - safe_strcat(response, status[i].name, maxlen); - safe_strcat(response, " ", maxlen); - } - } - /* make last character a newline */ - response[strlen(response)-1] = '\n'; - SAFE_FREE(status); - } - fstrcpy(state->response.data.winsresp,response); - return WINBINDD_OK; -} - -/* Get IP from hostname */ - -enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state) -{ - struct in_addr *ip_list; - int i, count, maxlen, size; - fstring response; - char * addr; - - /* Ensure null termination */ - state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - - DEBUG(3, ("[%5d]: wins_byname %s\n", state->pid, - state->request.data.winsreq)); - - *response = '\0'; - maxlen = sizeof(response) - 1; - - if ((ip_list = lookup_byname_backend(state->request.data.winsreq,&count))){ - for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr); - if (size > maxlen) { - SAFE_FREE(ip_list); - return WINBINDD_ERROR; - } - if (i != 0) { - /* Clear out the newline character */ - response[strlen(response)-1] = ' '; - } - safe_strcat(response,addr,maxlen); - safe_strcat(response,"\t",maxlen); - } - size = strlen(state->request.data.winsreq) + strlen(response); - if (size > maxlen) { - SAFE_FREE(ip_list); - return WINBINDD_ERROR; - } - safe_strcat(response,state->request.data.winsreq,maxlen); - safe_strcat(response,"\n",maxlen); - SAFE_FREE(ip_list); - } else - return WINBINDD_ERROR; - - fstrcpy(state->response.data.winsresp,response); - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/wins.c b/source4/nsswitch/wins.c deleted file mode 100644 index d5791d7af5..0000000000 --- a/source4/nsswitch/wins.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Unix SMB/CIFS implementation. - a WINS nsswitch module - Copyright (C) Andrew Tridgell 1999 - - 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" -#ifdef HAVE_NS_API_H -#undef VOLATILE - -#include <ns_daemon.h> -#endif - -#ifndef INADDRSZ -#define INADDRSZ 4 -#endif - -static int initialised; - -extern BOOL AllowDebugChange; - -/* Use our own create socket code so we don't recurse.... */ - -static int wins_lookup_open_socket_in(void) -{ - struct sockaddr_in sock; - int val=1; - int res; - - memset((char *)&sock,'\0',sizeof(sock)); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = 0; - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); - res = socket(AF_INET, SOCK_DGRAM, 0); - if (res == -1) - return -1; - - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif /* SO_REUSEPORT */ - - /* now we've got a socket - we need to bind it */ - - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { - close(res); - return(-1); - } - - set_socket_options(res,"SO_BROADCAST"); - - return res; -} - - -static void nss_wins_init(void) -{ - initialised = 1; - DEBUGLEVEL = 0; - AllowDebugChange = False; - - TimeInit(); - setup_logging("nss_wins",DEBUG_FILE); - lp_load(dyn_CONFIGFILE,True,False,False); - load_interfaces(); -} - -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - if (!initialised) { - nss_wins_init(); - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - -static struct in_addr *lookup_byname_backend(const char *name, int *count) -{ - int fd = -1; - struct in_addr *ret = NULL; - struct in_addr p; - int j, flags = 0; - - if (!initialised) { - nss_wins_init(); - } - - *count = 0; - - /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { - return ret; - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) { - return NULL; - } - - /* uggh, we have to broadcast to each interface in turn */ - for (j=iface_count() - 1;j >= 0;j--) { - struct in_addr *bcast = iface_n_bcast(j); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; - } - -out: - close(fd); - return ret; -} - - -#ifdef HAVE_NS_API_H -/* IRIX version */ - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n"); - nss_wins_init(); - return NSD_OK; -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - char *addr; - struct in_addr *ip_list; - struct node_status *status; - int i, count, len, size; - char response[1024]; - BOOL found = False; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! key || ! *key) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - response[0] = '\0'; - len = sizeof(response) - 2; - - /* - * response needs to be a string of the following format - * ip_address[ ip_address]*\tname[ alias]* - */ - if (strcasecmp(map,"hosts.byaddr") == 0) { - if ( status = lookup_byaddr_backend(key, &count)) { - size = strlen(key) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response,key,size); - strncat(response,"\t",1); - for (i = 0; i < count; i++) { - /* ignore group names */ - if (status[i].flags & 0x80) continue; - if (status[i].type == 0x20) { - size = sizeof(status[i].name) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response, status[i].name, size); - strncat(response, " ", 1); - found = True; - } - } - response[strlen(response)-1] = '\n'; - free(status); - } - } else if (strcasecmp(map,"hosts.byname") == 0) { - if (ip_list = lookup_byname_backend(key, &count)) { - for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - len -= size; - if (i != 0) - response[strlen(response)-1] = ' '; - strncat(response,addr,size); - strncat(response,"\t",1); - } - size = strlen(key) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - strncat(response,key,size); - strncat(response,"\n",1); - found = True; - free(ip_list); - } - } - - if (found) { - nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response); - nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE); - return NSD_OK; - } - nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n"); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -#else -/**************************************************************************** -gethostbyname() - we ignore any domain portion of the name and only -handle names that are at most 15 characters long - **************************************************************************/ -NSS_STATUS -_nss_wins_gethostbyname_r(const char *name, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) -{ - char **host_addresses; - struct in_addr *ip_list; - int i, count; - size_t namelen = strlen(name) + 1; - - memset(he, '\0', sizeof(*he)); - - ip_list = lookup_byname_backend(name, &count); - if (!ip_list) { - return NSS_STATUS_NOTFOUND; - } - - if (buflen < namelen + (2*count+1)*INADDRSZ) { - /* no ENOMEM error type?! */ - return NSS_STATUS_NOTFOUND; - } - - - host_addresses = (char **)buffer; - he->h_addr_list = host_addresses; - host_addresses[count] = NULL; - buffer += (count + 1) * INADDRSZ; - buflen += (count + 1) * INADDRSZ; - he->h_addrtype = AF_INET; - he->h_length = INADDRSZ; - - for (i=0;i<count;i++) { - memcpy(buffer, &ip_list[i].s_addr, INADDRSZ); - *host_addresses = buffer; - buffer += INADDRSZ; - buflen -= INADDRSZ; - host_addresses++; - } - - if (ip_list) - free(ip_list); - - memcpy(buffer, name, namelen); - he->h_name = buffer; - - return NSS_STATUS_SUCCESS; -} - - -NSS_STATUS -_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) -{ - if(af!=AF_INET) { - *h_errnop = NO_DATA; - *errnop = EAFNOSUPPORT; - return NSS_STATUS_UNAVAIL; - } - - return _nss_wins_gethostbyname_r(name,he,buffer,buflen,errnop,h_errnop); -} -#endif diff --git a/source4/printing/config.m4 b/source4/printing/config.m4 deleted file mode 100644 index ad5e4844e5..0000000000 --- a/source4/printing/config.m4 +++ /dev/null @@ -1,16 +0,0 @@ -############################################ -# for cups support we need libcups, and a handful of header files - -AC_ARG_ENABLE(cups, -[ --enable-cups Turn on CUPS support (default=auto)]) - -if test x$enable_cups != xno; then - AC_PATH_PROG(CUPS_CONFIG, cups-config) - - if test "x$CUPS_CONFIG" != x; then - AC_DEFINE(HAVE_CUPS,1,[Whether we have CUPS]) - CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`" - LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`" - PRINTLIBS="$PRINTLIBS `$CUPS_CONFIG --libs`" - fi -fi diff --git a/source4/printing/load.c b/source4/printing/load.c deleted file mode 100644 index cd90cbb6f3..0000000000 --- a/source4/printing/load.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - Unix SMB/CIFS implementation. - load printer lists - Copyright (C) Andrew Tridgell 1992-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" - - -/*************************************************************************** -auto-load printer services -***************************************************************************/ -void add_all_printers(void) -{ - int printers = lp_servicenumber(PRINTERS_NAME); - - if (printers < 0) return; - - pcap_printer_fn(lp_add_one_printer); -} - -/*************************************************************************** -auto-load some homes and printer services -***************************************************************************/ -static void add_auto_printers(void) -{ - const char *p; - int printers; - char *str = strdup(lp_auto_services()); - - if (!str) return; - - printers = lp_servicenumber(PRINTERS_NAME); - - if (printers < 0) { - SAFE_FREE(str); - return; - } - - for (p=strtok(str,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) { - if (lp_servicenumber(p) >= 0) continue; - - if (pcap_printername_ok(p,NULL)) { - lp_add_printer(p,printers); - } - } - - SAFE_FREE(str); -} - -/*************************************************************************** -load automatic printer services -***************************************************************************/ -void load_printers(void) -{ - add_auto_printers(); - if (lp_load_printers()) - add_all_printers(); -} diff --git a/source4/printing/lpq_parse.c b/source4/printing/lpq_parse.c deleted file mode 100644 index 4b91b8ac9a..0000000000 --- a/source4/printing/lpq_parse.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - Unix SMB/CIFS implementation. - lpq parsing routines - Copyright (C) Andrew Tridgell 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" - -static const char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"}; - - -/******************************************************************* -process time fields -********************************************************************/ -static time_t EntryTime(fstring tok[], int ptr, int count, int minimum) -{ - time_t jobtime,jobtime1; - - jobtime = time(NULL); /* default case: take current time */ - if (count >= minimum) { - struct tm *t; - int i, day, hour, min, sec; - char *c; - - for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */ - if (i<12) { - t = localtime(&jobtime); - day = atoi(tok[ptr+1]); - c=(char *)(tok[ptr+2]); - *(c+2)=0; - hour = atoi(c); - *(c+5)=0; - min = atoi(c+3); - if(*(c+6) != 0)sec = atoi(c+6); - else sec=0; - - if ((t->tm_mon < i)|| - ((t->tm_mon == i)&& - ((t->tm_mday < day)|| - ((t->tm_mday == day)&& - (t->tm_hour*60+t->tm_min < hour*60+min))))) - t->tm_year--; /* last year's print job */ - - t->tm_mon = i; - t->tm_mday = day; - t->tm_hour = hour; - t->tm_min = min; - t->tm_sec = sec; - jobtime1 = mktime(t); - if (jobtime1 != (time_t)-1) - jobtime = jobtime1; - } - } - return jobtime; -} - - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under bsd - -Warning: no daemon present -Rank Owner Job Files Total Size -1st tridge 148 README 8096 bytes - -here is an example of lpq output under osf/1 - -Warning: no daemon present -Rank Pri Owner Job Files Total Size -1st 0 tridge 148 README 8096 bytes - - -<allan@umich.edu> June 30, 1998. -Modified to handle file names with spaces, like the parse_lpq_lprng code -further below. -****************************************************************************/ -static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first) -{ -#ifdef OSF1 -#define RANKTOK 0 -#define PRIOTOK 1 -#define USERTOK 2 -#define JOBTOK 3 -#define FILETOK 4 -#define TOTALTOK (count - 2) -#define NTOK 6 -#define MAXTOK 128 -#else /* OSF1 */ -#define RANKTOK 0 -#define USERTOK 1 -#define JOBTOK 2 -#define FILETOK 3 -#define TOTALTOK (count - 2) -#define NTOK 5 -#define MAXTOK 128 -#endif /* OSF1 */ - - char *tok[MAXTOK]; - int count = 0; - pstring line2; - - pstrcpy(line2,line); - -#ifdef OSF1 - { - size_t length; - length = strlen(line2); - if (line2[length-3] == ':') - return(False); - } -#endif /* OSF1 */ - - /* FIXME: Use next_token rather than strtok! */ - tok[0] = strtok(line2," \t"); - count++; - - while (((tok[count] = strtok(NULL," \t")) != NULL) && (count < MAXTOK)) { - count++; - } - - /* we must get at least NTOK tokens */ - if (count < NTOK) - return(False); - - /* the Job and Total columns must be integer */ - if (!isdigit((int)*tok[JOBTOK]) || !isdigit((int)*tok[TOTALTOK])) return(False); - - buf->job = atoi(tok[JOBTOK]); - buf->size = atoi(tok[TOTALTOK]); - buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[USERTOK],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[FILETOK],sizeof(buf->fs_file)-1); - - if ((FILETOK + 1) != TOTALTOK) { - int i; - - for (i = (FILETOK + 1); i < TOTALTOK; i++) { - /* FIXME: Using fstrcat rather than other means is a bit - * inefficient; this might be a problem for enormous queues with - * many fields. */ - fstrcat(buf->fs_file, " "); - fstrcat(buf->fs_file, tok[i]); - } - /* Ensure null termination. */ - fstrterminate(buf->fs_file); - } - -#ifdef PRIOTOK - buf->priority = atoi(tok[PRIOTOK]); -#else - buf->priority = 1; -#endif - return(True); -} - -/* -<magnus@hum.auc.dk> -LPRng_time modifies the current date by inserting the hour and minute from -the lpq output. The lpq time looks like "23:15:07" - -<allan@umich.edu> June 30, 1998. -Modified to work with the re-written parse_lpq_lprng routine. - -<J.P.M.v.Itegem@tue.nl> Dec 17,1999 -Modified to work with lprng 3.16 -With lprng 3.16 The lpq time looks like - "23:15:07" - "23:15:07.100" - "1999-12-16-23:15:07" - "1999-12-16-23:15:07.100" - -*/ -static time_t LPRng_time(char *time_string) -{ - time_t jobtime; - struct tm t; - - jobtime = time(NULL); /* default case: take current time */ - t = *localtime(&jobtime); - - if ( atoi(time_string) < 24 ){ - t.tm_hour = atoi(time_string); - t.tm_min = atoi(time_string+3); - t.tm_sec = atoi(time_string+6); - } else { - t.tm_year = atoi(time_string)-1900; - t.tm_mon = atoi(time_string+5)-1; - t.tm_mday = atoi(time_string+8); - t.tm_hour = atoi(time_string+11); - t.tm_min = atoi(time_string+14); - t.tm_sec = atoi(time_string+17); - } - jobtime = mktime(&t); - - return jobtime; -} - - -/**************************************************************************** - parse a lprng lpq line - <allan@umich.edu> June 30, 1998. - Re-wrote this to handle file names with spaces, multiple file names on one - lpq line, etc; -****************************************************************************/ -static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPRNG_RANKTOK 0 -#define LPRNG_USERTOK 1 -#define LPRNG_PRIOTOK 2 -#define LPRNG_JOBTOK 3 -#define LPRNG_FILETOK 4 -#define LPRNG_TOTALTOK (num_tok - 2) -#define LPRNG_TIMETOK (num_tok - 1) -#define LPRNG_NTOK 7 -#define LPRNG_MAXTOK 128 /* PFMA just to keep us from running away. */ - - fstring tokarr[LPRNG_MAXTOK]; - const char *cptr; - char *ptr; - int num_tok = 0; - - cptr = line; - while(next_token( &cptr, tokarr[num_tok], " \t", sizeof(fstring)) && (num_tok < LPRNG_MAXTOK)) - num_tok++; - - /* We must get at least LPRNG_NTOK tokens. */ - if (num_tok < LPRNG_NTOK) { - return(False); - } - - if (!isdigit((int)*tokarr[LPRNG_JOBTOK]) || !isdigit((int)*tokarr[LPRNG_TOTALTOK])) { - return(False); - } - - buf->job = atoi(tokarr[LPRNG_JOBTOK]); - buf->size = atoi(tokarr[LPRNG_TOTALTOK]); - - if (strequal(tokarr[LPRNG_RANKTOK],"active")) { - buf->status = LPQ_PRINTING; - } else if (strequal(tokarr[LPRNG_RANKTOK],"done")) { - buf->status = LPQ_PRINTED; - } else if (isdigit((int)*tokarr[LPRNG_RANKTOK])) { - buf->status = LPQ_QUEUED; - } else { - buf->status = LPQ_PAUSED; - } - - buf->priority = *tokarr[LPRNG_PRIOTOK] -'A'; - - buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]); - - StrnCpy(buf->fs_user,tokarr[LPRNG_USERTOK],sizeof(buf->fs_user)-1); - - /* The '@hostname' prevents windows from displaying the printing icon - * for the current user on the taskbar. Plop in a null. - */ - - if ((ptr = strchr_m(buf->fs_user,'@')) != NULL) { - *ptr = '\0'; - } - - StrnCpy(buf->fs_file,tokarr[LPRNG_FILETOK],sizeof(buf->fs_file)-1); - - if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) { - int i; - - for (i = (LPRNG_FILETOK + 1); i < LPRNG_TOTALTOK; i++) { - /* FIXME: Using fstrcat rather than other means is a bit - * inefficient; this might be a problem for enormous queues with - * many fields. */ - fstrcat(buf->fs_file, " "); - fstrcat(buf->fs_file, tokarr[i]); - } - /* Ensure null termination. */ - fstrterminate(buf->fs_file); - } - - return(True); -} - - - -/******************************************************************* -parse lpq on an aix system - -Queue Dev Status Job Files User PP % Blks Cp Rnk -------- ----- --------- --- ------------------ ---------- ---- -- ----- --- --- -lazer lazer READY -lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1 - QUEUED 538 C.ps root@IEDVB 124 1 2 - QUEUED 539 E.ps root@IEDVB 28 1 3 - QUEUED 540 L.ps root@IEDVB 172 1 4 - QUEUED 541 P.ps root@IEDVB 22 1 5 -********************************************************************/ -static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[11]; - int count=0; - const char *cline = line; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; - count<10 && - next_token(&cline,tok[count],NULL, sizeof(tok[count])); - count++) ; - - /* we must get 6 tokens */ - if (count < 10) - { - if ((count == 7) && ((strcmp(tok[0],"QUEUED") == 0) || (strcmp(tok[0],"HELD") == 0))) - { - /* the 2nd and 5th columns must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4])) return(False); - buf->size = atoi(tok[4]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[2],' ')) - fstrcpy(tok[2],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[2],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[2],tmp); - } - } - - - buf->job = atoi(tok[1]); - buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[3],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); - } - else - { - DEBUG(6,("parse_lpq_aix count=%d\n", count)); - return(False); - } - } - else - { - /* the 4th and 9th columns must be integer */ - if (!isdigit((int)*tok[3]) || !isdigit((int)*tok[8])) return(False); - buf->size = atoi(tok[8]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[4],' ')) - fstrcpy(tok[4],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[4],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[4],tmp); - } - } - - - buf->job = atoi(tok[3]); - buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[5],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[4],sizeof(buf->fs_file)-1); - } - - - return(True); -} - - -/**************************************************************************** -parse a lpq line -here is an example of lpq output under hpux; note there's no space after -o ! -$> lpstat -oljplus -ljplus-2153 user priority 0 Jan 19 08:14 on ljplus - util.c 125697 bytes - server.c 110712 bytes -ljplus-2154 user priority 0 Jan 19 08:14 from client - (standard input) 7551 bytes -****************************************************************************/ -static BOOL parse_lpq_hpux(char *line, print_queue_struct *buf, BOOL first) -{ - /* must read two lines to process, therefore keep some values static */ - static BOOL header_line_ok=False, base_prio_reset=False; - static fstring jobuser; - static int jobid; - static int jobprio; - static time_t jobtime; - static int jobstat=LPQ_QUEUED; - /* to store minimum priority to print, lpstat command should be invoked - with -p option first, to work */ - static int base_prio; - int count; - char htab = '\011'; - const char *cline = line; - fstring tok[12]; - - /* If a line begins with a horizontal TAB, it is a subline type */ - - if (line[0] == htab) { /* subline */ - /* check if it contains the base priority */ - if (!strncmp(line,"\tfence priority : ",18)) { - base_prio=atoi(&line[18]); - DEBUG(4, ("fence priority set at %d\n", base_prio)); - } - if (!header_line_ok) return (False); /* incorrect header line */ - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; count<2 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - /* we must get 2 tokens */ - if (count < 2) return(False); - - /* the 2nd column must be integer */ - if (!isdigit((int)*tok[1])) return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[0],' ')) - fstrcpy(tok[0],"STDIN"); - - buf->size = atoi(tok[1]); - StrnCpy(buf->fs_file,tok[0],sizeof(buf->fs_file)-1); - - /* fill things from header line */ - buf->time = jobtime; - buf->job = jobid; - buf->status = jobstat; - buf->priority = jobprio; - StrnCpy(buf->fs_user,jobuser,sizeof(buf->fs_user)-1); - - return(True); - } - else { /* header line */ - header_line_ok=False; /* reset it */ - if (first) { - if (!base_prio_reset) { - base_prio=0; /* reset it */ - base_prio_reset=True; - } - } - else if (base_prio) base_prio_reset=False; - - /* handle the dash in the job id */ - string_sub(line,"-"," ",0); - - for (count=0; count<12 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 8 tokens */ - if (count < 8) return(False); - - /* first token must be printer name (cannot check ?) */ - /* the 2nd, 5th & 7th column must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False); - jobid = atoi(tok[1]); - StrnCpy(jobuser,tok[2],sizeof(buf->fs_user)-1); - jobprio = atoi(tok[4]); - - /* process time */ - jobtime=EntryTime(tok, 5, count, 8); - if (jobprio < base_prio) { - jobstat = LPQ_PAUSED; - DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat)); - } - else { - jobstat = LPQ_QUEUED; - if ((count >8) && (((strequal(tok[8],"on")) || - ((strequal(tok[8],"from")) && - ((count > 10)&&(strequal(tok[10],"on"))))))) - jobstat = LPQ_PRINTING; - } - - header_line_ok=True; /* information is correct */ - return(False); /* need subline info to include into queuelist */ - } -} - - -/**************************************************************************** -parse a lpstat line - -here is an example of "lpstat -o dcslw" output under sysv - -dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw -dcslw-897 tridge 4712 Dec 20 10:30:30 being held - -****************************************************************************/ -static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[9]; - int count=0; - char *p; - const char *cline = line; - - /* - * Handle the dash in the job id, but make sure that we skip over - * the printer name in case we have a dash in that. - * Patch from Dom.Mitchell@palmerharvey.co.uk. - */ - - /* - * Move to the first space. - */ - for (p = line ; !isspace(*p) && *p; p++) - ; - - /* - * Back up until the last '-' character or - * start of line. - */ - for (; (p >= line) && (*p != '-'); p--) - ; - - if((p >= line) && (*p == '-')) - *p = ' '; - - for (count=0; count<9 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) - ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 2nd and 4th, 6th columns must be integer */ - if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[3])) - return(False); - if (!isdigit((int)*tok[5])) - return(False); - - /* if the user contains a ! then trim the first part of it */ - if ((p=strchr_m(tok[2],'!'))) { - fstring tmp; - fstrcpy(tmp,p+1); - fstrcpy(tok[2],tmp); - } - - buf->job = atoi(tok[1]); - buf->size = atoi(tok[3]); - if (count > 7 && strequal(tok[7],"on")) - buf->status = LPQ_PRINTING; - else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held")) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - buf->priority = 0; - buf->time = EntryTime(tok, 4, count, 7); - StrnCpy(buf->fs_user,tok[2],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); - return(True); -} - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under qnx -Spooler: /qnx/spooler, on node 1 -Printer: txt (ready) -0000: root [job #1 ] active 1146 bytes /etc/profile -0001: root [job #2 ] ready 2378 bytes /etc/install -0002: root [job #3 ] ready 1146 bytes -- standard input -- -****************************************************************************/ -static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[7]; - int count=0; - const char *cline; - - DEBUG(4,("antes [%s]\n", line)); - - /* handle the case of "-- standard input --" as a filename */ - string_sub(line,"standard input","STDIN",0); - DEBUG(4,("despues [%s]\n", line)); - all_string_sub(line,"-- ","\"",0); - all_string_sub(line," --","\"",0); - DEBUG(4,("despues 1 [%s]\n", line)); - - string_sub(line,"[job #","",0); - string_sub(line,"]","",0); - DEBUG(4,("despues 2 [%s]\n", line)); - - for (count=0; count<7 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 3rd and 5th columns must be integer */ - if (!isdigit((int)*tok[2]) || !isdigit((int)*tok[4])) return(False); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[6],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[2]); - buf->size = atoi(tok[4]); - buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); - return(True); -} - - -/**************************************************************************** - parse a lpq line for the plp printing system - Bertrand Wallrich <Bertrand.Wallrich@loria.fr> - -redone by tridge. Here is a sample queue: - -Local Printer 'lp2' (fjall): - Printing (started at Jun 15 13:33:58, attempt 1). - Rank Owner Pr Opt Job Host Files Size Date - active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33 - 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33 - -****************************************************************************/ -static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[11]; - int count=0; - const char *cline = line; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"stdin","STDIN",0); - all_string_sub(line,"(","\"",0); - all_string_sub(line,")","\"",0); - - for (count=0; count<11 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 11 tokens */ - if (count < 11) - return(False); - - /* the first must be "active" or begin with an integer */ - if (strcmp(tok[0],"active") && !isdigit((int)tok[0][0])) - return(False); - - /* the 5th and 8th must be integer */ - if (!isdigit((int)*tok[4]) || !isdigit((int)*tok[7])) - return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr_m(tok[6],' ')) - fstrcpy(tok[6],"STDIN"); - - /* only take the last part of the filename */ - { - fstring tmp; - char *p = strrchr_m(tok[6],'/'); - if (p) - { - fstrcpy(tmp,p+1); - fstrcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[4]); - - buf->size = atoi(tok[7]); - if (strchr_m(tok[7],'K')) - buf->size *= 1024; - if (strchr_m(tok[7],'M')) - buf->size *= 1024*1024; - - buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); - return(True); -} - -/**************************************************************************** -parse a qstat line - -here is an example of "qstat -l -d qms" output under softq - -Queue qms: 2 jobs; daemon active (313); enabled; accepting; - job-ID submission-time pri size owner title -205980: H 98/03/09 13:04:05 0 15733 stephenf chap1.ps -206086:> 98/03/12 17:24:40 0 659 chris - -206087: 98/03/12 17:24:45 0 4876 chris - -Total: 21268 bytes in queue - - -****************************************************************************/ -static BOOL parse_lpq_softq(char *line,print_queue_struct *buf,BOOL first) -{ - fstring tok[10]; - int count=0; - const char *cline = line; - - /* mung all the ":"s to spaces*/ - string_sub(line,":"," ",0); - - for (count=0; count<10 && next_token(&cline,tok[count],NULL,sizeof(tok[count])); count++) ; - - /* we must get 9 tokens */ - if (count < 9) - return(False); - - /* the 1st and 7th columns must be integer */ - if (!isdigit((int)*tok[0]) || !isdigit((int)*tok[6])) return(False); - /* if the 2nd column is either '>' or 'H' then the 7th and 8th must be - * integer, else it's the 6th and 7th that must be - */ - if (*tok[1] == 'H' || *tok[1] == '>') - { - if (!isdigit((int)*tok[7])) - return(False); - buf->status = *tok[1] == '>' ? LPQ_PRINTING : LPQ_PAUSED; - count = 1; - } - else - { - if (!isdigit((int)*tok[5])) - return(False); - buf->status = LPQ_QUEUED; - count = 0; - } - - - buf->job = atoi(tok[0]); - buf->size = atoi(tok[count+6]); - buf->priority = atoi(tok[count+5]); - StrnCpy(buf->fs_user,tok[count+7],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[count+8],sizeof(buf->fs_file)-1); - buf->time = time(NULL); /* default case: take current time */ - { - time_t jobtime; - struct tm *t; - - t = localtime(&buf->time); - t->tm_mday = atoi(tok[count+2]+6); - t->tm_mon = atoi(tok[count+2]+3); - switch (*tok[count+2]) - { - case 7: case 8: case 9: t->tm_year = atoi(tok[count+2]); break; - default: t->tm_year = atoi(tok[count+2]); break; - } - - t->tm_hour = atoi(tok[count+3]); - t->tm_min = atoi(tok[count+4]); - t->tm_sec = atoi(tok[count+5]); - jobtime = mktime(t); - if (jobtime != (time_t)-1) - buf->time = jobtime; - } - - return(True); -} - -/******************************************************************* -parse lpq on an NT system - - Windows 2000 LPD Server - Printer \\10.0.0.2\NP17PCL (Paused) - -Owner Status Jobname Job-Id Size Pages Priority ----------------------------------------------------------------------------- -root (9.99. Printing /usr/lib/rhs/rhs-pr 3 625 0 1 -root (9.99. Paused /usr/lib/rhs/rhs-pr 4 625 0 1 -jmcd Waiting Re: Samba Open Sour 26 32476 1 1 - -********************************************************************/ -static BOOL parse_lpq_nt(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPRNT_OWNSIZ 11 -#define LPRNT_STATSIZ 9 -#define LPRNT_JOBSIZ 19 -#define LPRNT_IDSIZ 6 -#define LPRNT_SIZSIZ 9 - typedef struct - { - char owner[LPRNT_OWNSIZ]; - char space1; - char status[LPRNT_STATSIZ]; - char space2; - char jobname[LPRNT_JOBSIZ]; - char space3; - char jobid[LPRNT_IDSIZ]; - char space4; - char size[LPRNT_SIZSIZ]; - char terminator; - } nt_lpq_line; - - nt_lpq_line parse_line; -#define LPRNT_PRINTING "Printing" -#define LPRNT_WAITING "Waiting" -#define LPRNT_PAUSED "Paused" - - memset(&parse_line, '\0', sizeof(parse_line)); - strncpy((char *) &parse_line, line, sizeof(parse_line) -1); - - if (strlen((char *) &parse_line) != sizeof(parse_line) - 1) - return(False); - - /* Just want the first word in the owner field - the username */ - if (strchr_m(parse_line.owner, ' ')) - *(strchr_m(parse_line.owner, ' ')) = '\0'; - else - parse_line.space1 = '\0'; - - /* Make sure we have an owner */ - if (!strlen(parse_line.owner)) - return(False); - - /* Make sure the status is valid */ - parse_line.space2 = '\0'; - trim_string(parse_line.status, NULL, " "); - if (!strequal(parse_line.status, LPRNT_PRINTING) && - !strequal(parse_line.status, LPRNT_PAUSED) && - !strequal(parse_line.status, LPRNT_WAITING)) - return(False); - - parse_line.space3 = '\0'; - trim_string(parse_line.jobname, NULL, " "); - - buf->job = atoi(parse_line.jobid); - buf->priority = 0; - buf->size = atoi(parse_line.size); - buf->time = time(NULL); - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); - if (strequal(parse_line.status, LPRNT_PRINTING)) - buf->status = LPQ_PRINTING; - else if (strequal(parse_line.status, LPRNT_PAUSED)) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - - return(True); -} - -/******************************************************************* -parse lpq on an OS2 system - -JobID File Name Rank Size Status Comment ------ --------------- ------ -------- ------------ ------------ - 3 Control 1 68 Queued root@psflinu - 4 /etc/motd 2 11666 Queued root@psflinu - -********************************************************************/ -static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPROS2_IDSIZ 5 -#define LPROS2_JOBSIZ 15 -#define LPROS2_SIZSIZ 8 -#define LPROS2_STATSIZ 12 -#define LPROS2_OWNSIZ 12 - typedef struct - { - char jobid[LPROS2_IDSIZ]; - char space1[2]; - char jobname[LPROS2_JOBSIZ]; - char space2[14]; - char size[LPROS2_SIZSIZ]; - char space3[4]; - char status[LPROS2_STATSIZ]; - char space4[4]; - char owner[LPROS2_OWNSIZ]; - char terminator; - } os2_lpq_line; - - os2_lpq_line parse_line; -#define LPROS2_PRINTING "Printing" -#define LPROS2_WAITING "Queued" -#define LPROS2_PAUSED "Paused" - - memset(&parse_line, '\0', sizeof(parse_line)); - strncpy((char *) &parse_line, line, sizeof(parse_line) -1); - - if (strlen((char *) &parse_line) != sizeof(parse_line) - 1) - return(False); - - /* Get the jobid */ - buf->job = atoi(parse_line.jobid); - - /* Get the job name */ - parse_line.space2[0] = '\0'; - trim_string(parse_line.jobname, NULL, " "); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); - - buf->priority = 0; - buf->size = atoi(parse_line.size); - buf->time = time(NULL); - - /* Make sure we have an owner */ - if (!strlen(parse_line.owner)) - return(False); - - /* Make sure we have a valid status */ - parse_line.space4[0] = '\0'; - trim_string(parse_line.status, NULL, " "); - if (!strequal(parse_line.status, LPROS2_PRINTING) && - !strequal(parse_line.status, LPROS2_PAUSED) && - !strequal(parse_line.status, LPROS2_WAITING)) - return(False); - - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); - if (strequal(parse_line.status, LPROS2_PRINTING)) - buf->status = LPQ_PRINTING; - else if (strequal(parse_line.status, LPROS2_PAUSED)) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - - return(True); -} - -static const char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL }; -static const char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL }; -static const char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL }; - -#ifdef DEVELOPER - -/**************************************************************************** -parse a vlp line -****************************************************************************/ -static BOOL parse_lpq_vlp(char *line,print_queue_struct *buf,BOOL first) -{ - int toknum = 0; - fstring tok; - const char *cline = line; - - /* First line is printer status */ - - if (!isdigit(line[0])) return False; - - /* Parse a print job entry */ - - while(next_token(&cline, tok, NULL, sizeof(fstring))) { - switch (toknum) { - case 0: - buf->job = atoi(tok); - break; - case 1: - buf->size = atoi(tok); - break; - case 2: - buf->status = atoi(tok); - break; - case 3: - buf->time = atoi(tok); - break; - case 4: - fstrcpy(buf->fs_user, tok); - break; - case 5: - fstrcpy(buf->fs_file, tok); - break; - } - toknum++; - } - - return True; -} - -#endif /* DEVELOPER */ - -/**************************************************************************** -parse a lpq line. Choose printing style -****************************************************************************/ - -BOOL parse_lpq_entry(int snum,char *line, - print_queue_struct *buf, - print_status_struct *status,BOOL first) -{ - BOOL ret; - - switch (lp_printing(snum)) - { - case PRINT_SYSV: - ret = parse_lpq_sysv(line,buf,first); - break; - case PRINT_AIX: - ret = parse_lpq_aix(line,buf,first); - break; - case PRINT_HPUX: - ret = parse_lpq_hpux(line,buf,first); - break; - case PRINT_QNX: - ret = parse_lpq_qnx(line,buf,first); - break; - case PRINT_LPRNG: - ret = parse_lpq_lprng(line,buf,first); - break; - case PRINT_PLP: - ret = parse_lpq_plp(line,buf,first); - break; - case PRINT_SOFTQ: - ret = parse_lpq_softq(line,buf,first); - break; - case PRINT_LPRNT: - ret = parse_lpq_nt(line,buf,first); - break; - case PRINT_LPROS2: - ret = parse_lpq_os2(line,buf,first); - break; -#ifdef DEVELOPER - case PRINT_VLP: - case PRINT_TEST: - ret = parse_lpq_vlp(line,buf,first); - break; -#endif /* DEVELOPER */ - default: - ret = parse_lpq_bsd(line,buf,first); - break; - } - - /* We don't want the newline in the status message. */ - { - char *p = strchr_m(line,'\n'); - if (p) *p = 0; - } - - /* in the LPRNG case, we skip lines starting by a space.*/ - if (line && !ret && (lp_printing(snum)==PRINT_LPRNG) ) - { - if (line[0]==' ') - return ret; - } - - - if (status && !ret) - { - /* a few simple checks to see if the line might be a - printer status line: - handle them so that most severe condition is shown */ - int i; - strlower(line); - - switch (status->status) { - case LPSTAT_OK: - for (i=0; stat0_strings[i]; i++) - if (strstr(line,stat0_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_OK; - return ret; - } - case LPSTAT_STOPPED: - for (i=0; stat1_strings[i]; i++) - if (strstr(line,stat1_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_STOPPED; - return ret; - } - case LPSTAT_ERROR: - for (i=0; stat2_strings[i]; i++) - if (strstr(line,stat2_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_ERROR; - return ret; - } - break; - } - } - - return(ret); -} diff --git a/source4/printing/notify.c b/source4/printing/notify.c deleted file mode 100644 index a745e9e308..0000000000 --- a/source4/printing/notify.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 2.2 - printing backend routines - Copyright (C) Tim Potter, 2002 - Copyright (C) Gerald Carter, 2002 - - 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 "printing.h" - -static TALLOC_CTX *send_ctx; - -static BOOL create_send_ctx(void) -{ - if (!send_ctx) - send_ctx = talloc_init("print notify queue"); - - if (!send_ctx) - return False; - - return True; -} - -/**************************************************************************** - Turn a queue name into a snum. -****************************************************************************/ - -int print_queue_snum(const char *qname) -{ - int snum = lp_servicenumber(qname); - if (snum == -1 || !lp_print_ok(snum)) - return -1; - return snum; -} - -/******************************************************************* - Used to decide if we need a short select timeout. -*******************************************************************/ - -BOOL print_notify_messages_pending(void) -{ - return (notify_queue_head != NULL); -} - -/******************************************************************* - Flatten data into a message. -*******************************************************************/ - -static BOOL flatten_message(struct notify_queue *q) -{ - struct spoolss_notify_msg *msg = q->msg; - char *buf = NULL; - size_t buflen = 0, len; - -again: - len = 0; - - /* Pack header */ - - len += tdb_pack(buf + len, buflen - len, "f", msg->printer); - - len += tdb_pack(buf + len, buflen - len, "ddddd", - msg->type, msg->field, msg->id, msg->len, msg->flags); - - /* Pack data */ - - if (msg->len == 0) - len += tdb_pack(buf + len, buflen - len, "dd", - msg->notify.value[0], msg->notify.value[1]); - else - len += tdb_pack(buf + len, buflen - len, "B", - msg->len, msg->notify.data); - - if (buflen != len) { - buf = talloc_realloc(send_ctx, buf, len); - if (!buf) - return False; - buflen = len; - goto again; - } - - q->buf = buf; - q->buflen = buflen; - - return True; -} - -/******************************************************************* - Send the batched messages - on a per-printer basis. -*******************************************************************/ - -static void print_notify_send_messages_to_printer(const char *printer, unsigned int timeout) -{ - char *buf; - struct notify_queue *pq, *pq_next; - size_t msg_count = 0, offset = 0; - size_t num_pids = 0; - size_t i; - pid_t *pid_list = NULL; - - /* Count the space needed to send the messages. */ - for (pq = notify_queue_head; pq; pq = pq->next) { - if (strequal(printer, pq->msg->printer)) { - if (!flatten_message(pq)) { - DEBUG(0,("print_notify_send_messages: Out of memory\n")); - talloc_destroy_pool(send_ctx); - return; - } - offset += (pq->buflen + 4); - msg_count++; - } - } - offset += 4; /* For count. */ - - buf = talloc(send_ctx, offset); - if (!buf) { - DEBUG(0,("print_notify_send_messages: Out of memory\n")); - talloc_destroy_pool(send_ctx); - return; - } - - offset = 0; - SIVAL(buf,offset,msg_count); - offset += 4; - for (pq = notify_queue_head; pq; pq = pq_next) { - pq_next = pq->next; - - if (strequal(printer, pq->msg->printer)) { - SIVAL(buf,offset,pq->buflen); - offset += 4; - memcpy(buf + offset, pq->buf, pq->buflen); - offset += pq->buflen; - - /* Remove from list. */ - DLIST_REMOVE(notify_queue_head, pq); - } - } - - DEBUG(5, ("print_notify_send_messages_to_printer: sending %d print notify message%s to printer %s\n", - msg_count, msg_count != 1 ? "s" : "", printer)); - - /* - * Get the list of PID's to send to. - */ - - if (!print_notify_pid_list(printer, send_ctx, &num_pids, &pid_list)) - return; - - for (i = 0; i < num_pids; i++) - message_send_pid_with_timeout(pid_list[i], MSG_PRINTER_NOTIFY2, buf, offset, True, timeout); -} - -/******************************************************************* - Actually send the batched messages. -*******************************************************************/ - -void print_notify_send_messages(unsigned int timeout) -{ - if (!print_notify_messages_pending()) - return; - - if (!create_send_ctx()) - return; - - while (print_notify_messages_pending()) - print_notify_send_messages_to_printer(notify_queue_head->msg->printer, timeout); - - talloc_destroy_pool(send_ctx); -} - -/********************************************************************** - deep copy a SPOOLSS_NOTIFY_MSG structure using a TALLOC_CTX - *********************************************************************/ - -static BOOL copy_notify2_msg( SPOOLSS_NOTIFY_MSG *to, SPOOLSS_NOTIFY_MSG *from ) -{ - - if ( !to || !from ) - return False; - - memcpy( to, from, sizeof(SPOOLSS_NOTIFY_MSG) ); - - if ( from->len ) { - to->notify.data = talloc_memdup(send_ctx, from->notify.data, from->len ); - if ( !to->notify.data ) { - DEBUG(0,("copy_notify2_msg: talloc_memdup() of size [%d] failed!\n", from->len )); - return False; - } - } - - - return True; -} - -/******************************************************************* - Batch up print notify messages. -*******************************************************************/ - -static void send_spoolss_notify2_msg(SPOOLSS_NOTIFY_MSG *msg) -{ - struct notify_queue *pnqueue; - - /* - * Ensure we only have one message unique to each name/type/field/id/flags - * tuple. There is no point in sending multiple messages that match - * as they will just cause flickering updates in the client. - */ - - for (tmp_ptr = notify_queue_head; tmp_ptr; tmp_ptr = tmp_ptr->next) { - if (tmp_ptr->msg->type == msg->type && - tmp_ptr->msg->field == msg->field && - tmp_ptr->msg->id == msg->id && - tmp_ptr->msg->flags == msg->flags && - strequal(tmp_ptr->msg->printer, msg->printer)) { - - DEBUG(5, ("send_spoolss_notify2_msg: replacing message 0x%02x/0x%02x for printer %s \ -in notify_queue\n", msg->type, msg->field, msg->printer)); - - tmp_ptr->msg = msg; - return; - } - } - - /* Store the message on the pending queue. */ - - pnqueue = talloc(send_ctx, sizeof(*pnqueue)); - if (!pnqueue) { - DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n")); - return; - } - - /* allocate a new msg structure and copy the fields */ - - if ( !(pnqueue->msg = (SPOOLSS_NOTIFY_MSG*)talloc(send_ctx, sizeof(SPOOLSS_NOTIFY_MSG))) ) { - DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%d] failed!\n", - sizeof(SPOOLSS_NOTIFY_MSG))); - return; - } - copy_notify2_msg(pnqueue->msg, msg); - pnqueue->buf = NULL; - pnqueue->buflen = 0; - - DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x for printer %s \ -to notify_queue_head\n", msg->type, msg->field, msg->printer)); - - /* - * Note we add to the end of the list to ensure - * the messages are sent in the order they were received. JRA. - */ - - DLIST_ADD_END(notify_queue_head, pnqueue, struct notify_queue *); -} - -static void send_notify_field_values(const char *printer_name, uint32 type, - uint32 field, uint32 id, uint32 value1, - uint32 value2, uint32 flags) -{ - struct spoolss_notify_msg *msg; - - if (lp_disable_spoolss()) - return; - - if (!create_send_ctx()) - return; - - msg = (struct spoolss_notify_msg *)talloc(send_ctx, sizeof(struct spoolss_notify_msg)); - if (!msg) - return; - - ZERO_STRUCTP(msg); - - fstrcpy(msg->printer, printer_name); - msg->type = type; - msg->field = field; - msg->id = id; - msg->notify.value[0] = value1; - msg->notify.value[1] = value2; - msg->flags = flags; - - send_spoolss_notify2_msg(msg); -} - -static void send_notify_field_buffer(const char *printer_name, uint32 type, - uint32 field, uint32 id, uint32 len, - char *buffer) -{ - struct spoolss_notify_msg *msg; - - if (lp_disable_spoolss()) - return; - - if (!create_send_ctx()) - return; - - msg = (struct spoolss_notify_msg *)talloc(send_ctx, sizeof(struct spoolss_notify_msg)); - if (!msg) - return; - - ZERO_STRUCTP(msg); - - fstrcpy(msg->printer, printer_name); - msg->type = type; - msg->field = field; - msg->id = id; - msg->len = len; - msg->notify.data = buffer; - - send_spoolss_notify2_msg(msg); -} - -/* Send a message that the printer status has changed */ - -void notify_printer_status_byname(const char *printer_name, uint32 status) -{ - /* Printer status stored in value1 */ - - send_notify_field_values(printer_name, PRINTER_NOTIFY_TYPE, - PRINTER_NOTIFY_STATUS, 0, - status, 0, 0); -} - -void notify_printer_status(int snum, uint32 status) -{ - const char *printer_name = SERVICE(snum); - - if (printer_name) - notify_printer_status_byname(printer_name, status); -} - -void notify_job_status_byname(const char *printer_name, uint32 jobid, uint32 status, - uint32 flags) -{ - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_STATUS, jobid, - status, 0, flags); -} - -void notify_job_status(int snum, uint32 jobid, uint32 status) -{ - const char *printer_name = SERVICE(snum); - - notify_job_status_byname(printer_name, jobid, status, 0); -} - -void notify_job_total_bytes(int snum, uint32 jobid, uint32 size) -{ - const char *printer_name = SERVICE(snum); - - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_TOTAL_BYTES, jobid, - size, 0, 0); -} - -void notify_job_total_pages(int snum, uint32 jobid, uint32 pages) -{ - const char *printer_name = SERVICE(snum); - - /* Job id stored in id field, status in value1 */ - - send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, - JOB_NOTIFY_TOTAL_PAGES, jobid, - pages, 0, 0); -} - -void notify_job_username(int snum, uint32 jobid, char *name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, - jobid, strlen(name) + 1, name); -} - -void notify_job_name(int snum, uint32 jobid, char *name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, - jobid, strlen(name) + 1, name); -} - -void notify_job_submitted(int snum, uint32 jobid, time_t submitted) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, - jobid, sizeof(submitted), (char *)&submitted); -} - -void notify_printer_driver(int snum, char *driver_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, - snum, strlen(driver_name) + 1, driver_name); -} - -void notify_printer_comment(int snum, char *comment) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, - snum, strlen(comment) + 1, comment); -} - -void notify_printer_sharename(int snum, char *share_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, - snum, strlen(share_name) + 1, share_name); -} - -void notify_printer_port(int snum, char *port_name) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, - snum, strlen(port_name) + 1, port_name); -} - -void notify_printer_location(int snum, char *location) -{ - const char *printer_name = SERVICE(snum); - - send_notify_field_buffer( - printer_name, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, - snum, strlen(location) + 1, location); -} - -void notify_printer_byname( char *printername, uint32 change, char *value ) -{ - int snum = print_queue_snum(printername); - int type = PRINTER_NOTIFY_TYPE; - - if ( snum == -1 ) - return; - - send_notify_field_buffer( printername, type, change, snum, strlen(value)+1, value ); -} - - -/**************************************************************************** - Return a malloced list of pid_t's that are interested in getting update - messages on this print queue. Used in printing/notify to send the messages. -****************************************************************************/ - -BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t *p_num_pids, pid_t **pp_pid_list) -{ - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - TDB_DATA data; - BOOL ret = True; - size_t i, num_pids, offset; - pid_t *pid_list; - - *p_num_pids = 0; - *pp_pid_list = NULL; - - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - - if (tdb_read_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_pid_list: Failed to lock printer %s database\n", - printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - if (!data.dptr) { - ret = True; - goto done; - } - - num_pids = data.dsize / 8; - - if ((pid_list = (pid_t *)talloc(mem_ctx, sizeof(pid_t) * num_pids)) == NULL) { - ret = False; - goto done; - } - - for( i = 0, offset = 0; offset < data.dsize; offset += 8, i++) - pid_list[i] = (pid_t)IVAL(data.dptr, offset); - - *pp_pid_list = pid_list; - *p_num_pids = num_pids; - - ret = True; - - done: - - tdb_read_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} diff --git a/source4/printing/pcap.c b/source4/printing/pcap.c deleted file mode 100644 index c399c3c6cc..0000000000 --- a/source4/printing/pcap.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printcap parsing - Copyright (C) Karl Auer 1993-1998 - - Re-working by Martin Kiff, 1994 - - Re-written again by Andrew Tridgell - - Modified for SVID support by Norm Jacobs, 1997 - - Modified for CUPS support by Michael Sweet, 1999 - - 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. -*/ - -/* - * Parse printcap file. - * - * This module does exactly one thing - it looks into the printcap file - * and tells callers if a specified string appears as a printer name. - * - * The way this module looks at the printcap file is very simplistic. - * Only the local printcap file is inspected (no searching of NIS - * databases etc). - * - * There are assumed to be one or more printer names per record, held - * as a set of sub-fields separated by vertical bar symbols ('|') in the - * first field of the record. The field separator is assumed to be a colon - * ':' and the record separator a newline. - * - * Lines ending with a backspace '\' are assumed to flag that the following - * line is a continuation line so that a set of lines can be read as one - * printcap entry. - * - * A line stating with a hash '#' is assumed to be a comment and is ignored - * Comments are discarded before the record is strung together from the - * set of continuation lines. - * - * Opening a pipe for "lpc status" and reading that would probably - * be pretty effective. Code to do this already exists in the freely - * distributable PCNFS server code. - * - * Modified to call SVID/XPG4 support if printcap name is set to "lpstat" - * in smb.conf under Solaris. - * - * Modified to call CUPS support if printcap name is set to "cups" - * in smb.conf. - */ - -#include "includes.h" - -#ifdef AIX -/* ****************************************** - Extend for AIX system and qconfig file - from 'boulard@univ-rennes1.fr - ****************************************** */ -static int strlocate(char *xpLine,char *xpS) -{ - int iS,iL,iRet; - char *p; - iS = strlen(xpS); - iL = strlen(xpLine); - - iRet = 0; - p = xpLine; - while (iL >= iS) - { - if (strncmp(p,xpS,iS) == 0) {iRet =1;break;}; - p++; - iL--; - } - /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/ - - return(iRet); -} - - -/* ******************************************************************* */ -/* * Scan qconfig and search all virtual printer (device printer) * */ -/* ******************************************************************* */ -static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *)) -{ - int iEtat; - XFILE *pfile; - char *line,*p; - pstring name,comment; - line = NULL; - *name = 0; - *comment = 0; - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - return; - } - - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* locate an entry */ - if (*line == '\t' || *line == ' ') continue; - if ((p=strchr_m(line,':'))) - { - *p = '\0'; - p = strtok(line,":"); - if (strcmp(p,"bsh")!=0) - { - pstrcpy(name,p); - iEtat = 1; - continue; - } - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - fn(name,comment); - iEtat = 0; - continue; - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - fn(name,comment); - iEtat = 0; - continue; - } - break; - } - } - x_fclose(pfile); -} - -/* Scan qconfig file and locate de printername */ - -static BOOL ScanQconfig(char *psz,char *pszPrintername) -{ - int iLg,iEtat; - XFILE *pfile; - char *pName; - char *line; - - pName = NULL; - line = NULL; - if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0)) - pName = malloc(iLg+10); - if (pName == NULL) - { - DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername)); - return(False); - } - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - SAFE_FREE(pName); - return(False); - } - slprintf(pName, iLg + 9, "%s:",pszPrintername); - iLg = strlen(pName); - /*DEBUG(3,( " Looking for entry %s\n",pName));*/ - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* scanning entry */ - if (strncmp(line,pName,iLg) == 0) - { - iEtat = 1; - continue; - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - free (line); - SAFE_FREE(pName); - fclose(pfile); - return(True); - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - free (line); - SAFE_FREE(pName); - fclose(pfile); - return(True); - } - break; - } - } - free (pName); - x_fclose(pfile); - return(False); -} -#endif /* AIX */ - - -/*************************************************************************** -Scan printcap file pszPrintcapname for a printer called pszPrintername. -Return True if found, else False. Returns False on error, too, after logging -the error at level 0. For generality, the printcap name may be passed - if -passed as NULL, the configuration will be queried for the name. -***************************************************************************/ -BOOL pcap_printername_ok(const char *pszPrintername, const char *pszPrintcapname) -{ - char *line=NULL; - const char *psz; - char *p,*q; - XFILE *pfile; - - if (pszPrintername == NULL || pszPrintername[0] == '\0') - { - DEBUG(0,( "Attempt to locate null printername! Internal error?\n")); - return(False); - } - - /* only go looking if no printcap name supplied */ - if ((psz = pszPrintcapname) == NULL || psz[0] == '\0') - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return(False); - } - -#ifdef HAVE_CUPS - if (strequal(psz, "cups")) - return (cups_printername_ok(pszPrintername)); -#endif /* HAVE_CUPS */ - -#ifdef SYSV - if (strequal(psz, "lpstat")) - return (sysv_printername_ok(pszPrintername)); -#endif - -#ifdef AIX - if (strlocate(psz,"/qconfig")) - return(ScanQconfig(psz,pszPrintername)); -#endif - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return(False); - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr_m(line,':'); - if (p) *p = 0; - - /* now just check if the name is in the list */ - /* NOTE: I avoid strtok as the fn calling this one may be using it */ - for (p=line; p; p=q) - { - if ((q = strchr_m(p,'|'))) *q++ = 0; - - if (strequal(p,pszPrintername)) - { - SAFE_FREE(line); - x_fclose(pfile); - return(True); - } - p = q; - } - } - - x_fclose(pfile); - return(False); -} - - -/*************************************************************************** -run a function on each printer name in the printcap file. The function is -passed the primary name and the comment (if possible). Note the fn() takes -strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed -to return DOS codepage. FIXME !! JRA. -***************************************************************************/ -void pcap_printer_fn(void (*fn)(char *, char *)) -{ - pstring name,comment; - char *line; - char *psz; - char *p,*q; - XFILE *pfile; - - /* only go looking if no printcap name supplied */ - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return; - } - -#ifdef HAVE_CUPS - if (strequal(psz, "cups")) { - cups_printer_fn(fn); - return; - } -#endif /* HAVE_CUPS */ - -#ifdef SYSV - if (strequal(psz, "lpstat")) { - sysv_printer_fn(fn); - return; - } -#endif - -#ifdef AIX - if (strlocate(psz,"/qconfig")) - { - ScanQconfig_fn(psz,fn); - return; - } -#endif - - if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return; - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr_m(line,':'); - if (p) *p = 0; - - /* now find the most likely printer name and comment - this is pure guesswork, but it's better than nothing */ - *name = 0; - *comment = 0; - for (p=line; p; p=q) - { - BOOL has_punctuation; - if ((q = strchr_m(p,'|'))) *q++ = 0; - - has_punctuation = (strchr_m(p,' ') || strchr_m(p,'\t') || strchr_m(p,'(') || strchr_m(p,')')); - - if (strlen(p)>strlen(comment) && has_punctuation) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - - if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation) - { - if (!*comment) pstrcpy(comment,name); - pstrcpy(name,p); - continue; - } - - if (!strchr_m(comment,' ') && - strlen(p) > strlen(comment)) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - } - - comment[60] = 0; - name[MAXPRINTERLEN] = 0; - - if (*name) - fn(name,comment); - } - x_fclose(pfile); -} diff --git a/source4/printing/print_cups.c b/source4/printing/print_cups.c deleted file mode 100644 index 7cf21c966e..0000000000 --- a/source4/printing/print_cups.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Support code for the Common UNIX Printing System ("CUPS") - * - * Copyright 1999-2003 by Michael R Sweet. - * - * 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 "printing.h" - -#ifdef HAVE_CUPS -#include <cups/cups.h> -#include <cups/language.h> - - -/* - * CUPS printing interface definitions... - */ - -static int cups_job_delete(int snum, struct printjob *pjob); -static int cups_job_pause(int snum, struct printjob *pjob); -static int cups_job_resume(int snum, struct printjob *pjob); -static int cups_job_submit(int snum, struct printjob *pjob); -static int cups_queue_get(int snum, print_queue_struct **q, - print_status_struct *status); -static int cups_queue_pause(int snum); -static int cups_queue_resume(int snum); - - -struct printif cups_printif = - { - cups_queue_get, - cups_queue_pause, - cups_queue_resume, - cups_job_delete, - cups_job_pause, - cups_job_resume, - cups_job_submit, - }; - -/* - * 'cups_passwd_cb()' - The CUPS password callback... - */ - -static const char * /* O - Password or NULL */ -cups_passwd_cb(const char *prompt) /* I - Prompt */ -{ - /* - * Always return NULL to indicate that no password is available... - */ - - return (NULL); -} - - -/* - * 'cups_printer_fn()' - Call a function for every printer known to the - * system. - */ - -void cups_printer_fn(void (*fn)(char *, char *)) -{ - /* I - Function to call */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ - char *name, /* printer-name attribute */ - *make_model, /* printer-make-and-model attribute */ - *info; /* printer-info attribute */ - static const char *requested[] =/* Requested attributes */ - { - "printer-name", - "printer-make-and-model", - "printer-info" - }; - - - DEBUG(5,("cups_printer_fn(%p)\n", fn)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return; - } - - /* - * Build a CUPS_GET_PRINTERS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - */ - - request = ippNew(); - - request->request.op.operation_id = CUPS_GET_PRINTERS; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(requested) / sizeof(requested[0])), - NULL, requested); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer list - %s\n", - ippErrorString(cupsLastError()))); - httpClose(http); - return; - } - - for (attr = response->attrs; attr != NULL;) - { - /* - * Skip leading attributes until we hit a printer... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Pull the needed attributes from this printer... - */ - - name = NULL; - make_model = NULL; - info = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (name == NULL) - break; - - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - - } - - ippDelete(response); - - - /* - * Build a CUPS_GET_CLASSES request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - */ - - request = ippNew(); - - request->request.op.operation_id = CUPS_GET_CLASSES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(requested) / sizeof(requested[0])), - NULL, requested); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer list - %s\n", - ippErrorString(cupsLastError()))); - httpClose(http); - return; - } - - for (attr = response->attrs; attr != NULL;) - { - /* - * Skip leading attributes until we hit a printer... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Pull the needed attributes from this printer... - */ - - name = NULL; - make_model = NULL; - info = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (name == NULL) - break; - - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - - } - - ippDelete(response); - - /* - * Close the connection to the server... - */ - - httpClose(http); -} - - -/* - * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok() - * for CUPS. - * O - 1 if printer name OK - * I - Name of printer - */ -int cups_printername_ok(const char *name) -{ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_printername_ok(\"%s\")\n", name)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(3,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (0); - } - - /* - * Build an IPP_GET_PRINTER_ATTRS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", NULL, "printer-uri"); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(cupsLastError()))); - httpClose(http); - return (0); - } - - httpClose(http); - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(response->request.status.status_code))); - ippDelete(response); - return (0); - } - else - { - ippDelete(response); - return (1); - } -} - - -/* - * 'cups_job_delete()' - Delete a job. - */ - -static int -cups_job_delete(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_CANCEL_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_CANCEL_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_pause()' - Pause a job. - */ - -static int -cups_job_pause(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_HOLD_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_HOLD_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_resume()' - Resume a paused job. - */ - -static int -cups_job_resume(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_RELEASE_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * job-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_RELEASE_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_job_submit()' - Submit a job for printing. - */ - -static int -cups_job_submit(int snum, struct printjob *pjob) -{ - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_PRINT_JOB request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - * [document-data] - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_PRINT_JOB; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "job-originating-host-name", NULL, - get_remote_machine_name()); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, - pjob->jobname); - - /* - * Do the request and get back a response... - */ - - slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum)); - - ret = 1; - if ((response = cupsDoFileRequest(http, request, uri, - pjob->filename)) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - if ( ret == 0 ) - unlink(pjob->filename); - /* else print_job_end will do it for us */ - - return (ret); -} - - -/* - * 'cups_queue_get()' - Get all the jobs in the print queue. - */ - -static int -cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status) -{ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - int qcount, /* Number of active queue entries */ - qalloc; /* Number of queue entries allocated */ - print_queue_struct *queue, /* Queue entries */ - *temp; /* Temporary pointer for queue */ - const char *user_name, /* job-originating-user-name attribute */ - *job_name; /* job-name attribute */ - int job_id; /* job-id attribute */ - int job_k_octets; /* job-k-octets attribute */ - time_t job_time; /* time-at-creation attribute */ - ipp_jstate_t job_status; /* job-status attribute */ - int job_priority; /* job-priority attribute */ - static const char *jattrs[] = /* Requested job attributes */ - { - "job-id", - "job-k-octets", - "job-name", - "job-originating-user-name", - "job-priority", - "job-state", - "time-at-creation", - }; - static const char *pattrs[] = /* Requested printer attributes */ - { - "printer-state", - "printer-state-message" - }; - - - DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (0); - } - - /* - * Generate the printer URI... - */ - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - /* - * Build an IPP_GET_JOBS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_JOBS; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(jattrs) / sizeof(jattrs[0])), - NULL, jattrs); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get jobs for %s - %s\n", uri, - ippErrorString(cupsLastError()))); - httpClose(http); - return (0); - } - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(0,("Unable to get jobs for %s - %s\n", uri, - ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - - return (0); - } - - /* - * Process the jobs... - */ - - qcount = 0; - qalloc = 0; - queue = NULL; - - for (attr = response->attrs; attr != NULL; attr = attr->next) - { - /* - * Skip leading attributes until we hit a job... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_JOB) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Allocate memory as needed... - */ - if (qcount >= qalloc) - { - qalloc += 16; - - temp = Realloc(queue, sizeof(print_queue_struct) * qalloc); - - if (temp == NULL) - { - DEBUG(0,("cups_queue_get: Not enough memory!")); - ippDelete(response); - httpClose(http); - - SAFE_FREE(queue); - return (0); - } - - queue = temp; - } - - temp = queue + qcount; - memset(temp, 0, sizeof(print_queue_struct)); - - /* - * Pull the needed attributes from this job... - */ - - job_id = 0; - job_priority = 50; - job_status = IPP_JOB_PENDING; - job_time = 0; - job_k_octets = 0; - user_name = NULL; - job_name = NULL; - - while (attr != NULL && attr->group_tag == IPP_TAG_JOB) - { - if (attr->name == NULL) - { - attr = attr->next; - break; - } - - if (strcmp(attr->name, "job-id") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_id = attr->values[0].integer; - - if (strcmp(attr->name, "job-k-octets") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_k_octets = attr->values[0].integer; - - if (strcmp(attr->name, "job-priority") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_priority = attr->values[0].integer; - - if (strcmp(attr->name, "job-state") == 0 && - attr->value_tag == IPP_TAG_ENUM) - job_status = (ipp_jstate_t)(attr->values[0].integer); - - if (strcmp(attr->name, "time-at-creation") == 0 && - attr->value_tag == IPP_TAG_INTEGER) - job_time = attr->values[0].integer; - - if (strcmp(attr->name, "job-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - job_name = attr->values[0].string.text; - - if (strcmp(attr->name, "job-originating-user-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - user_name = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (user_name == NULL || job_name == NULL || job_id == 0) - { - if (attr == NULL) - break; - else - continue; - } - - temp->job = job_id; - temp->size = job_k_octets * 1024; - temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED : - job_status == IPP_JOB_STOPPED ? LPQ_PAUSED : - job_status == IPP_JOB_HELD ? LPQ_PAUSED : - LPQ_PRINTING; - temp->priority = job_priority; - temp->time = job_time; - strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1); - strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1); - - qcount ++; - - if (attr == NULL) - break; - } - - ippDelete(response); - - /* - * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the - * following attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", - (sizeof(pattrs) / sizeof(pattrs[0])), - NULL, pattrs); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); - - /* - * Do the request and get back a response... - */ - - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - httpClose(http); - *q = queue; - return (qcount); - } - - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum), - ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - *q = queue; - return (qcount); - } - - /* - * Get the current printer status and convert it to the SAMBA values. - */ - - if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) - { - if (attr->values[0].integer == IPP_PRINTER_STOPPED) - status->status = LPSTAT_STOPPED; - else - status->status = LPSTAT_OK; - } - - if ((attr = ippFindAttribute(response, "printer-state-message", - IPP_TAG_TEXT)) != NULL) - fstrcpy(status->message, attr->values[0].string.text); - - ippDelete(response); - - /* - * Return the job queue... - */ - - httpClose(http); - - *q = queue; - return (qcount); -} - - -/* - * 'cups_queue_pause()' - Pause a print queue. - */ - -static int -cups_queue_pause(int snum) -{ - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_queue_pause(%d)\n", snum)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_PAUSE_PRINTER request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_PAUSE_PRINTER; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -/* - * 'cups_queue_resume()' - Restart a print queue. - */ - -static int -cups_queue_resume(int snum) -{ - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - - - DEBUG(5,("cups_queue_resume(%d)\n", snum)); - - /* - * Make sure we don't ask for passwords... - */ - - cupsSetPasswordCB(cups_passwd_cb); - - /* - * Try to connect to the server... - */ - - if ((http = httpConnect(cupsServer(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cupsServer(), strerror(errno))); - return (1); - } - - /* - * Build an IPP_RESUME_PRINTER request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * printer-uri - * requesting-user-name - */ - - request = ippNew(); - - request->request.op.operation_id = IPP_RESUME_PRINTER; - request->request.op.request_id = 1; - - language = cupsLangDefault(); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); - - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); - - /* - * Do the request and get back a response... - */ - - ret = 1; - - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - - httpClose(http); - - return (ret); -} - - -#else - /* this keeps fussy compilers happy */ - void print_cups_dummy(void) {} -#endif /* HAVE_CUPS */ diff --git a/source4/printing/print_generic.c b/source4/printing/print_generic.c deleted file mode 100644 index aae2844ded..0000000000 --- a/source4/printing/print_generic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printing command routines - Copyright (C) Andrew Tridgell 1992-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 "printing.h" - - -/* - * Generic printing interface definitions... - */ - -static int generic_job_delete(int snum, struct printjob *pjob); -static int generic_job_pause(int snum, struct printjob *pjob); -static int generic_job_resume(int snum, struct printjob *pjob); -static int generic_job_submit(int snum, struct printjob *pjob); -static int generic_queue_get(int snum, print_queue_struct **q, - print_status_struct *status); -static int generic_queue_pause(int snum); -static int generic_queue_resume(int snum); - - -struct printif generic_printif = - { - generic_queue_get, - generic_queue_pause, - generic_queue_resume, - generic_job_delete, - generic_job_pause, - generic_job_resume, - generic_job_submit, - }; - -/**************************************************************************** -run a given print command -a null terminated list of value/substitute pairs is provided -for local substitution strings -****************************************************************************/ -static int print_run_command(int snum,char *command, int *outfd, ...) -{ - - pstring syscmd; - char *arg; - int ret; - va_list ap; - va_start(ap, outfd); - - if (!command || !*command) return -1; - - if (!VALID_SNUM(snum)) { - DEBUG(0,("Invalid snum %d for command %s\n", snum, command)); - return -1; - } - - pstrcpy(syscmd, command); - - while ((arg = va_arg(ap, char *))) { - char *value = va_arg(ap,char *); - pstring_sub(syscmd, arg, value); - } - va_end(ap); - - pstring_sub(syscmd, "%p", PRINTERNAME(snum)); - standard_sub_snum(snum,syscmd,sizeof(syscmd)); - - ret = smbrun(syscmd,outfd); - - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - - return ret; -} - - -/**************************************************************************** -delete a print job -****************************************************************************/ -static int generic_job_delete(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to delete the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command( - snum, - lp_lprmcommand(snum), NULL, - "%j", jobstr, - "%T", timestring(pjob->starttime), - NULL); -} - -/**************************************************************************** -pause a job -****************************************************************************/ -static int generic_job_pause(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to pause the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command(snum, - lp_lppausecommand(snum), NULL, - "%j", jobstr, - NULL); -} - -/**************************************************************************** -resume a job -****************************************************************************/ -static int generic_job_resume(int snum, struct printjob *pjob) -{ - fstring jobstr; - - /* need to pause the spooled entry */ - slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command(snum, - lp_lpresumecommand(snum), NULL, - "%j", jobstr, - NULL); -} - -/**************************************************************************** - Submit a file for printing - called from print_job_end() -****************************************************************************/ - -static int generic_job_submit(int snum, struct printjob *pjob) -{ - int ret; - pstring current_directory; - pstring print_directory; - char *wd, *p; - pstring jobname; - fstring job_page_count, job_size; - - /* we print from the directory path to give the best chance of - parsing the lpq output */ - wd = sys_getwd(current_directory); - if (!wd) - return 0; - - pstrcpy(print_directory, pjob->filename); - p = strrchr_m(print_directory,'/'); - if (!p) - return 0; - *p++ = 0; - - if (chdir(print_directory) != 0) - return 0; - - pstrcpy(jobname, pjob->jobname); - pstring_sub(jobname, "'", "_"); - slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count); - slprintf(job_size, sizeof(job_size)-1, "%d", pjob->size); - - /* send it to the system spooler */ - ret = print_run_command(snum, - lp_printcommand(snum), NULL, - "%s", p, - "%J", jobname, - "%f", p, - "%z", job_size, - "%c", job_page_count, - NULL); - - chdir(wd); - - return ret; -} - - -/**************************************************************************** -get the current list of queued jobs -****************************************************************************/ -static int generic_queue_get(int snum, print_queue_struct **q, print_status_struct *status) -{ - char **qlines; - int fd; - int numlines, i, qcount; - print_queue_struct *queue = NULL; - fstring printer_name; - - fstrcpy(printer_name, lp_servicename(snum)); - - print_run_command(snum, lp_lpqcommand(snum), &fd, NULL); - - if (fd == -1) { - DEBUG(5,("generic_queue_get: Can't read print queue status for printer %s\n", - printer_name )); - return 0; - } - - numlines = 0; - qlines = fd_lines_load(fd, &numlines); - close(fd); - - /* turn the lpq output into a series of job structures */ - qcount = 0; - ZERO_STRUCTP(status); - if (numlines) - queue = (print_queue_struct *)malloc(sizeof(print_queue_struct)*(numlines+1)); - - if (queue) { - for (i=0; i<numlines; i++) { - /* parse the line */ - if (parse_lpq_entry(snum,qlines[i], - &queue[qcount],status,qcount==0)) { - qcount++; - } - } - } - file_lines_free(qlines); - - *q = queue; - return qcount; -} - -/**************************************************************************** - pause a queue -****************************************************************************/ -static int generic_queue_pause(int snum) -{ - return print_run_command(snum, lp_queuepausecommand(snum), NULL, NULL); -} - -/**************************************************************************** - resume a queue -****************************************************************************/ -static int generic_queue_resume(int snum) -{ - return print_run_command(snum, lp_queueresumecommand(snum), NULL, NULL); -} diff --git a/source4/printing/print_svid.c b/source4/printing/print_svid.c deleted file mode 100644 index 07b157bcd9..0000000000 --- a/source4/printing/print_svid.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 1997-1998 by Norm Jacobs, Colorado Springs, Colorado, USA - * Copyright (C) 1997-1998 by Sun Microsystem, Inc. - * All Rights Reserved - * - * 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. - */ - -/* - * This module implements support for gathering and comparing available - * printer information on a SVID or XPG4 compliant system. It does this - * through the use of the SVID/XPG4 command "lpstat(1)". - * - * The expectations is that execution of the command "lpstat -v" will - * generate responses in the form of: - * - * device for serial: /dev/term/b - * system for fax: server - * system for color: server (as printer chroma) - */ - - -#include "includes.h" - -#ifdef SYSV - -typedef struct printer { - char *name; - struct printer *next; -} printer_t; -static printer_t *printers = NULL; - -static void populate_printers(void) -{ - char **lines; - int i; - - lines = file_lines_pload("/usr/bin/lpstat -v", NULL); - if (!lines) return; - - for (i=0;lines[i];i++) { - printer_t *ptmp; - char *name, *tmp; - char *buf = lines[i]; - - /* eat "system/device for " */ - if (((tmp = strchr_m(buf, ' ')) == NULL) || - ((tmp = strchr_m(++tmp, ' ')) == NULL)) - continue; - - /* - * In case we're only at the "for ". - */ - - if(!strncmp("for ",++tmp,4)) { - tmp=strchr_m(tmp, ' '); - tmp++; - } - - /* Eat whitespace. */ - - while(*tmp == ' ') - ++tmp; - - /* - * On HPUX there is an extra line that can be ignored. - * d.thibadeau 2001/08/09 - */ - if(!strncmp("remote to",tmp,9)) - continue; - - name = tmp; - - /* truncate the ": ..." */ - if ((tmp = strchr_m(name, ':')) != NULL) - *tmp = '\0'; - - /* add it to the cache */ - if ((ptmp = malloc(sizeof (*ptmp))) != NULL) { - ZERO_STRUCTP(ptmp); - if((ptmp->name = strdup(name)) == NULL) - DEBUG(0,("populate_printers: malloc fail in strdup !\n")); - ptmp->next = printers; - printers = ptmp; - } else { - DEBUG(0,("populate_printers: malloc fail for ptmp\n")); - } - } - - file_lines_free(lines); -} - - -/* - * provide the equivalent of pcap_printer_fn() for SVID/XPG4 conforming - * systems. It was unclear why pcap_printer_fn() was tossing names longer - * than 8 characters. I suspect that its a protocol limit, but amazingly - * names longer than 8 characters appear to work with my test - * clients (Win95/NT). - */ -void sysv_printer_fn(void (*fn)(char *, char *)) -{ - printer_t *tmp; - - if (printers == NULL) - populate_printers(); - for (tmp = printers; tmp != NULL; tmp = tmp->next) - (fn)(tmp->name, ""); -} - - -/* - * provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming - * systems. - */ -int sysv_printername_ok(const char *name) -{ - printer_t *tmp; - - if (printers == NULL) - populate_printers(); - for (tmp = printers; tmp != NULL; tmp = tmp->next) - if (strcmp(tmp->name, name) == 0) - return (True); - return (False); -} - -#else -/* this keeps fussy compilers happy */ - void print_svid_dummy(void); - void print_svid_dummy(void) {} -#endif diff --git a/source4/printing/printfsp.c b/source4/printing/printfsp.c deleted file mode 100644 index 5d230f8be4..0000000000 --- a/source4/printing/printfsp.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - Unix SMB/CIFS implementation. - printing backend routines for smbd - using files_struct rather - than only snum - Copyright (C) Andrew Tridgell 1992-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" - -/*************************************************************************** -open a print file and setup a fsp for it. This is a wrapper around -print_job_start(). -***************************************************************************/ - -files_struct *print_fsp_open(struct tcon_context *conn, char *fname) -{ - int jobid; - SMB_STRUCT_STAT sbuf; - extern struct current_user current_user; - files_struct *fsp = file_new(conn); - fstring name; - - if(!fsp) - return NULL; - - fstrcpy( name, "Remote Downlevel Document"); - if (fname) { - char *p = strrchr(fname, '/'); - fstrcat(name, " "); - if (!p) - p = fname; - fstrcat(name, p); - } - - jobid = print_job_start(¤t_user, SNUM(conn), name, NULL); - if (jobid == -1) { - file_free(fsp); - return NULL; - } - - /* Convert to RAP id. */ - fsp->rap_print_jobid = pjobid_to_rap(SNUM(conn), jobid); - if (fsp->rap_print_jobid == 0) { - /* We need to delete the entry in the tdb. */ - pjob_delete(SNUM(conn), jobid); - file_free(fsp); - return NULL; - } - - /* setup a full fsp */ - fsp->fd = print_job_fd(SNUM(conn),jobid); - GetTimeOfDay(&fsp->open_time); - fsp->vuid = current_user.vuid; - fsp->size = 0; - fsp->pos = -1; - fsp->can_lock = True; - fsp->can_read = False; - fsp->can_write = True; - fsp->share_mode = 0; - fsp->print_file = True; - fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; - fsp->sent_oplock_break = NO_BREAK_SENT; - fsp->is_directory = False; - fsp->directory_delete_on_close = False; - string_set(&fsp->fsp_name,print_job_fname(SNUM(conn),jobid)); - fsp->wbmpx_ptr = NULL; - fsp->wcp = NULL; - conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf); - fsp->mode = sbuf.st_mode; - fsp->inode = sbuf.st_ino; - fsp->dev = sbuf.st_dev; - - conn->num_files_open++; - - return fsp; -} - -/**************************************************************************** -print a file - called on closing the file -****************************************************************************/ -void print_fsp_end(files_struct *fsp, BOOL normal_close) -{ - uint32 jobid; - int snum; - - if (fsp->share_mode == FILE_DELETE_ON_CLOSE) { - /* - * Truncate the job. print_job_end will take - * care of deleting it for us. JRA. - */ - sys_ftruncate(fsp->fd, 0); - } - - if (fsp->fsp_name) { - string_free(&fsp->fsp_name); - } - - if (!rap_to_pjobid(fsp->rap_print_jobid, &snum, &jobid)) { - DEBUG(3,("print_fsp_end: Unable to convert RAP jobid %u to print jobid.\n", - (unsigned int)fsp->rap_print_jobid )); - return; - } - - print_job_end(SNUM(fsp->conn),jobid, normal_close); -} diff --git a/source4/printing/printing.c b/source4/printing/printing.c deleted file mode 100644 index e4d9e5f785..0000000000 --- a/source4/printing/printing.c +++ /dev/null @@ -1,2128 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0 - printing backend routines - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 2002 - - 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 "printing.h" - -/* Current printer interface */ -static struct printif *current_printif = &generic_printif; - -/* - the printing backend revolves around a tdb database that stores the - SMB view of the print queue - - The key for this database is a jobid - a internally generated number that - uniquely identifies a print job - - reading the print queue involves two steps: - - possibly running lpq and updating the internal database from that - - reading entries from the database - - jobids are assigned when a job starts spooling. -*/ - -/*************************************************************************** - Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32 - bit RPC jobids.... JRA. -***************************************************************************/ - -static TDB_CONTEXT *rap_tdb; -static uint16 next_rap_jobid; - -uint16 pjobid_to_rap(int snum, uint32 jobid) -{ - uint16 rap_jobid; - TDB_DATA data, key; - char jinfo[8]; - - DEBUG(10,("pjobid_to_rap: called.\n")); - - if (!rap_tdb) { - /* Create the in-memory tdb. */ - rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); - if (!rap_tdb) - return 0; - } - - SIVAL(&jinfo,0,(int32)snum); - SIVAL(&jinfo,4,jobid); - - key.dptr = (char *)&jinfo; - key.dsize = sizeof(jinfo); - data = tdb_fetch(rap_tdb, key); - if (data.dptr && data.dsize == sizeof(uint16)) { - memcpy(&rap_jobid, data.dptr, sizeof(uint16)); - SAFE_FREE(data.dptr); - DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n", - (unsigned int)jobid, - (unsigned int)rap_jobid)); - return rap_jobid; - } - SAFE_FREE(data.dptr); - /* Not found - create and store mapping. */ - rap_jobid = ++next_rap_jobid; - if (rap_jobid == 0) - rap_jobid = ++next_rap_jobid; - data.dptr = (char *)&rap_jobid; - data.dsize = sizeof(rap_jobid); - tdb_store(rap_tdb, key, data, TDB_REPLACE); - tdb_store(rap_tdb, data, key, TDB_REPLACE); - - DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n", - (unsigned int)jobid, - (unsigned int)rap_jobid)); - return rap_jobid; -} - -BOOL rap_to_pjobid(uint16 rap_jobid, int *psnum, uint32 *pjobid) -{ - TDB_DATA data, key; - - DEBUG(10,("rap_to_pjobid called.\n")); - - if (!rap_tdb) - return False; - - key.dptr = (char *)&rap_jobid; - key.dsize = sizeof(rap_jobid); - data = tdb_fetch(rap_tdb, key); - if (data.dptr && data.dsize == 8) { - *psnum = IVAL(data.dptr,0); - *pjobid = IVAL(data.dptr,4); - DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n", - (unsigned int)*pjobid, - (unsigned int)rap_jobid)); - SAFE_FREE(data.dptr); - return True; - } - - DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n", - (unsigned int)rap_jobid)); - SAFE_FREE(data.dptr); - return False; -} - -static void rap_jobid_delete(int snum, uint32 jobid) -{ - TDB_DATA key, data; - uint16 rap_jobid; - char jinfo[8]; - - DEBUG(10,("rap_jobid_delete: called.\n")); - - if (!rap_tdb) - return; - - SIVAL(&jinfo,0,(int32)snum); - SIVAL(&jinfo,4,jobid); - - key.dptr = (char *)&jinfo; - key.dsize = sizeof(jinfo); - data = tdb_fetch(rap_tdb, key); - if (!data.dptr || (data.dsize != sizeof(uint16))) { - DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n", - (unsigned int)jobid )); - SAFE_FREE(data.dptr); - return; - } - - DEBUG(10,("rap_jobid_delete: deleting jobid %u\n", - (unsigned int)jobid )); - - memcpy(&rap_jobid, data.dptr, sizeof(uint16)); - SAFE_FREE(data.dptr); - data.dptr = (char *)&rap_jobid; - data.dsize = sizeof(rap_jobid); - tdb_delete(rap_tdb, key); - tdb_delete(rap_tdb, data); -} - -static pid_t local_pid; - -static int get_queue_status(int, print_status_struct *); - -/**************************************************************************** - Initialise the printing backend. Called once at startup before the fork(). -****************************************************************************/ - -BOOL print_backend_init(void) -{ - const char *sversion = "INFO/version"; - pstring printing_path; - int services = lp_numservices(); - int snum; - - if (local_pid == sys_getpid()) - return True; - - unlink(lock_path("printing.tdb")); - pstrcpy(printing_path,lock_path("printing")); - mkdir(printing_path,0755); - - local_pid = sys_getpid(); - - /* handle a Samba upgrade */ - - for (snum = 0; snum < services; snum++) { - struct tdb_print_db *pdb; - if (!lp_print_ok(snum)) - continue; - - pdb = get_print_db_byname(lp_const_servicename(snum)); - if (!pdb) - continue; - if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) { - DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) )); - release_print_db(pdb); - return False; - } - if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) { - tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL); - tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION); - } - tdb_unlock_bystring(pdb->tdb, sversion); - release_print_db(pdb); - } - - close_all_print_db(); /* Don't leave any open. */ - - /* select the appropriate printing interface... */ -#ifdef HAVE_CUPS - if (strcmp(lp_printcapname(), "cups") == 0) - current_printif = &cups_printif; -#endif /* HAVE_CUPS */ - - /* do NT print initialization... */ - return nt_printing_init(); -} - -/**************************************************************************** - Shut down printing backend. Called once at shutdown to close the tdb. -****************************************************************************/ - -void printing_end(void) -{ - close_all_print_db(); /* Don't leave any open. */ -} - -/**************************************************************************** - Useful function to generate a tdb key. -****************************************************************************/ - -static TDB_DATA print_key(uint32 jobid) -{ - static uint32 j; - TDB_DATA ret; - - j = jobid; - ret.dptr = (void *)&j; - ret.dsize = sizeof(j); - return ret; -} - -/*********************************************************************** - unpack a pjob from a tdb buffer -***********************************************************************/ - -int unpack_pjob( char* buf, int buflen, struct printjob *pjob ) -{ - int len = 0; - int used; - - if ( !buf || !pjob ) - return -1; - - len += tdb_unpack(buf+len, buflen-len, "dddddddddffff", - &pjob->pid, - &pjob->sysjob, - &pjob->fd, - &pjob->starttime, - &pjob->status, - &pjob->size, - &pjob->page_count, - &pjob->spooled, - &pjob->smbjob, - pjob->filename, - pjob->jobname, - pjob->user, - pjob->queuename); - - if ( len == -1 ) - return -1; - - if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 ) - return -1; - - len += used; - - return len; - -} - -/**************************************************************************** - Useful function to find a print job in the database. -****************************************************************************/ - -static struct printjob *print_job_find(int snum, uint32 jobid) -{ - static struct printjob pjob; - TDB_DATA ret; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - - - if (!pdb) - return NULL; - - ret = tdb_fetch(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - - if (!ret.dptr) - return NULL; - - if ( pjob.nt_devmode ) - free_nt_devicemode( &pjob.nt_devmode ); - - ZERO_STRUCT( pjob ); - - if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) { - SAFE_FREE(ret.dptr); - return NULL; - } - - SAFE_FREE(ret.dptr); - return &pjob; -} - -/* Convert a unix jobid to a smb jobid */ - -static uint32 sysjob_to_jobid_value; - -static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *state) -{ - struct printjob *pjob; - int *sysjob = (int *)state; - - if (!data.dptr || data.dsize == 0) - return 0; - - pjob = (struct printjob *)data.dptr; - if (key.dsize != sizeof(uint32)) - return 0; - - if (*sysjob == pjob->sysjob) { - uint32 *jobid = (uint32 *)key.dptr; - - sysjob_to_jobid_value = *jobid; - return 1; - } - - return 0; -} - -/**************************************************************************** - This is a *horribly expensive call as we have to iterate through all the - current printer tdb's. Don't do this often ! JRA. -****************************************************************************/ - -uint32 sysjob_to_jobid(int unix_jobid) -{ - int services = lp_numservices(); - int snum; - - sysjob_to_jobid_value = (uint32)-1; - - for (snum = 0; snum < services; snum++) { - struct tdb_print_db *pdb; - if (!lp_print_ok(snum)) - continue; - pdb = get_print_db_byname(lp_const_servicename(snum)); - if (pdb) - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid); - release_print_db(pdb); - if (sysjob_to_jobid_value != (uint32)-1) - return sysjob_to_jobid_value; - } - return (uint32)-1; -} - -/**************************************************************************** - Send notifications based on what has changed after a pjob_store. -****************************************************************************/ - -static struct { - uint32 lpq_status; - uint32 spoolss_status; -} lpq_to_spoolss_status_map[] = { - { LPQ_QUEUED, JOB_STATUS_QUEUED }, - { LPQ_PAUSED, JOB_STATUS_PAUSED }, - { LPQ_SPOOLING, JOB_STATUS_SPOOLING }, - { LPQ_PRINTING, JOB_STATUS_PRINTING }, - { LPQ_DELETING, JOB_STATUS_DELETING }, - { LPQ_OFFLINE, JOB_STATUS_OFFLINE }, - { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT }, - { LPQ_PRINTED, JOB_STATUS_PRINTED }, - { LPQ_DELETED, JOB_STATUS_DELETED }, - { LPQ_BLOCKED, JOB_STATUS_BLOCKED }, - { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION }, - { -1, 0 } -}; - -/* Convert a lpq status value stored in printing.tdb into the - appropriate win32 API constant. */ - -static uint32 map_to_spoolss_status(uint32 lpq_status) -{ - int i = 0; - - while (lpq_to_spoolss_status_map[i].lpq_status != -1) { - if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status) - return lpq_to_spoolss_status_map[i].spoolss_status; - i++; - } - - return 0; -} - -static void pjob_store_notify(int snum, uint32 jobid, struct printjob *old_data, - struct printjob *new_data) -{ - BOOL new_job = False; - - if (!old_data) - new_job = True; - - /* Notify the job name first */ - - if (new_job || !strequal(old_data->jobname, new_data->jobname)) - notify_job_name(snum, jobid, new_data->jobname); - - /* Job attributes that can't be changed. We only send - notification for these on a new job. */ - - if (new_job) { - notify_job_submitted(snum, jobid, new_data->starttime); - notify_job_username(snum, jobid, new_data->user); - } - - /* Job attributes of a new job or attributes that can be - modified. */ - - if (new_job || old_data->status != new_data->status) - notify_job_status(snum, jobid, map_to_spoolss_status(new_data->status)); - - if (new_job || old_data->size != new_data->size) - notify_job_total_bytes(snum, jobid, new_data->size); - - if (new_job || old_data->page_count != new_data->page_count) - notify_job_total_pages(snum, jobid, new_data->page_count); -} - -/**************************************************************************** - Store a job structure back to the database. -****************************************************************************/ - -static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob) -{ - TDB_DATA old_data, new_data; - BOOL ret = False; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - char *buf = NULL; - int len, newlen, buflen; - - - if (!pdb) - return False; - - /* Get old data */ - - old_data = tdb_fetch(pdb->tdb, print_key(jobid)); - - /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */ - - newlen = 0; - - do { - len = 0; - buflen = newlen; - len += tdb_pack(buf+len, buflen-len, "dddddddddffff", - pjob->pid, - pjob->sysjob, - pjob->fd, - pjob->starttime, - pjob->status, - pjob->size, - pjob->page_count, - pjob->spooled, - pjob->smbjob, - pjob->filename, - pjob->jobname, - pjob->user, - pjob->queuename); - - len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len); - - if (buflen != len) { - char *tb; - - tb = (char *)Realloc(buf, len); - if (!tb) { - DEBUG(0,("pjob_store: failed to enlarge buffer!\n")); - goto done; - } - else - buf = tb; - newlen = len; - } - } while ( buflen != len ); - - - /* Store new data */ - - new_data.dptr = buf; - new_data.dsize = len; - ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0); - - release_print_db(pdb); - - /* Send notify updates for what has changed */ - - if ( ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob)) ) - pjob_store_notify( snum, jobid, (struct printjob *)old_data.dptr, pjob ); - -done: - SAFE_FREE( old_data.dptr ); - SAFE_FREE( buf ); - - return ret; -} - -/**************************************************************************** - Remove a job structure from the database. -****************************************************************************/ - -void pjob_delete(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - uint32 job_status = 0; - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - - if (!pdb) - return; - - if (!pjob) { - DEBUG(5, ("pjob_delete(): we were asked to delete nonexistent job %u\n", - (unsigned int)jobid)); - release_print_db(pdb); - return; - } - - /* Send a notification that a job has been deleted */ - - job_status = map_to_spoolss_status(pjob->status); - - /* We must cycle through JOB_STATUS_DELETING and - JOB_STATUS_DELETED for the port monitor to delete the job - properly. */ - - job_status |= JOB_STATUS_DELETING; - notify_job_status(snum, jobid, job_status); - - job_status |= JOB_STATUS_DELETED; - notify_job_status(snum, jobid, job_status); - - /* Remove from printing.tdb */ - - tdb_delete(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - rap_jobid_delete(snum, jobid); -} - -/**************************************************************************** - Parse a file name from the system spooler to generate a jobid. -****************************************************************************/ - -static uint32 print_parse_jobid(char *fname) -{ - int jobid; - - if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0) - return (uint32)-1; - fname += strlen(PRINT_SPOOL_PREFIX); - - jobid = atoi(fname); - if (jobid <= 0) - return (uint32)-1; - - return (uint32)jobid; -} - -/**************************************************************************** - List a unix job in the print database. -****************************************************************************/ - -static void print_unix_job(int snum, print_queue_struct *q, uint32 jobid) -{ - struct printjob pj, *old_pj; - - if (jobid == (uint32)-1) - jobid = q->job + UNIX_JOB_START; - - /* Preserve the timestamp on an existing unix print job */ - - old_pj = print_job_find(snum, jobid); - - ZERO_STRUCT(pj); - - pj.pid = (pid_t)-1; - pj.sysjob = q->job; - pj.fd = -1; - pj.starttime = old_pj ? old_pj->starttime : q->time; - pj.status = q->status; - pj.size = q->size; - pj.spooled = True; - pj.smbjob = (old_pj != NULL ? True : False); - fstrcpy(pj.filename, old_pj ? old_pj->filename : ""); - if (jobid < UNIX_JOB_START) - fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document"); - else - fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file); - fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user); - fstrcpy(pj.queuename, old_pj ? old_pj->queuename : lp_const_servicename(snum)); - - pjob_store(snum, jobid, &pj); -} - - -struct traverse_struct { - print_queue_struct *queue; - int qcount, snum, maxcount, total_jobs; - time_t lpq_time; -}; - -/**************************************************************************** - Utility fn to delete any jobs that are no longer active. -****************************************************************************/ - -static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_struct *ts = (struct traverse_struct *)state; - struct printjob pjob; - uint32 jobid; - int i; - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - free_nt_devicemode( &pjob.nt_devmode ); - - - if (ts->snum != lp_servicenumber(pjob.queuename)) { - /* this isn't for the queue we are looking at - this cannot happen with the split tdb's. JRA */ - return 0; - } - - if (!pjob.smbjob) { - /* remove a unix job if it isn't in the system queue any more */ - - for (i=0;i<ts->qcount;i++) { - uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START); - if (jobid == u_jobid) - break; - } - if (i == ts->qcount) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - return 0; - } - - /* maybe it hasn't been spooled yet */ - if (!pjob.spooled) { - /* if a job is not spooled and the process doesn't - exist then kill it. This cleans up after smbd - deaths */ - if (!process_exists(pjob.pid)) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - return 0; - } - - for (i=0;i<ts->qcount;i++) { - uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file); - if (jobid == curr_jobid) - break; - } - - /* The job isn't in the system queue - we have to assume it has - completed, so delete the database entry. */ - - if (i == ts->qcount) { - - /* A race can occur between the time a job is spooled and - when it appears in the lpq output. This happens when - the job is added to printing.tdb when another smbd - running print_queue_update() has completed a lpq and - is currently traversing the printing tdb and deleting jobs. - Don't delete the job if it was submitted after the lpq_time. */ - - if (pjob.starttime < ts->lpq_time) - pjob_delete(ts->snum, jobid); - else - ts->total_jobs++; - } - else - ts->total_jobs++; - - return 0; -} - -/**************************************************************************** - Check if the print queue has been updated recently enough. -****************************************************************************/ - -static void print_cache_flush(int snum) -{ - fstring key; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - - if (!pdb) - return; - slprintf(key, sizeof(key)-1, "CACHE/%s", printername); - tdb_store_int32(pdb->tdb, key, -1); - release_print_db(pdb); -} - -/**************************************************************************** - Check if someone already thinks they are doing the update. -****************************************************************************/ - -static pid_t get_updating_pid(fstring printer_name) -{ - fstring keystr; - TDB_DATA data, key; - pid_t updating_pid; - struct tdb_print_db *pdb = get_print_db_byname(printer_name); - - if (!pdb) - return (pid_t)-1; - slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - data = tdb_fetch(pdb->tdb, key); - release_print_db(pdb); - if (!data.dptr || data.dsize != sizeof(pid_t)) { - SAFE_FREE(data.dptr); - return (pid_t)-1; - } - - memcpy(&updating_pid, data.dptr, sizeof(pid_t)); - SAFE_FREE(data.dptr); - - if (process_exists(updating_pid)) - return updating_pid; - - return (pid_t)-1; -} - -/**************************************************************************** - Set the fact that we're doing the update, or have finished doing the update - in the tdb. -****************************************************************************/ - -static void set_updating_pid(const fstring printer_name, BOOL delete) -{ - fstring keystr; - TDB_DATA key; - TDB_DATA data; - pid_t updating_pid = sys_getpid(); - struct tdb_print_db *pdb = get_print_db_byname(printer_name); - - if (!pdb) - return; - - slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - if (delete) { - tdb_delete(pdb->tdb, key); - release_print_db(pdb); - return; - } - - data.dptr = (void *)&updating_pid; - data.dsize = sizeof(pid_t); - - tdb_store(pdb->tdb, key, data, TDB_REPLACE); - release_print_db(pdb); -} - -/**************************************************************************** - Update the internal database from the system print queue for a queue. -****************************************************************************/ - -static void print_queue_update(int snum) -{ - int i, qcount; - print_queue_struct *queue = NULL; - print_status_struct status; - print_status_struct old_status; - struct printjob *pjob; - struct traverse_struct tstruct; - fstring keystr, printer_name, cachestr; - TDB_DATA data, key; - struct tdb_print_db *pdb; - - fstrcpy(printer_name, lp_const_servicename(snum)); - pdb = get_print_db_byname(printer_name); - if (!pdb) - return; - - /* - * Check to see if someone else is doing this update. - * This is essentially a mutex on the update. - */ - - if (get_updating_pid(printer_name) != -1) { - release_print_db(pdb); - return; - } - - /* Lock the queue for the database update */ - - slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name); - /* Only wait 10 seconds for this. */ - if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) { - DEBUG(0,("print_queue_update: Failed to lock printer %s database\n", printer_name)); - release_print_db(pdb); - return; - } - - /* - * Ensure that no one else got in here. - * If the updating pid is still -1 then we are - * the winner. - */ - - if (get_updating_pid(printer_name) != -1) { - /* - * Someone else is doing the update, exit. - */ - tdb_unlock_bystring(pdb->tdb, keystr); - release_print_db(pdb); - return; - } - - /* - * We're going to do the update ourselves. - */ - - /* Tell others we're doing the update. */ - set_updating_pid(printer_name, False); - - /* - * Allow others to enter and notice we're doing - * the update. - */ - - tdb_unlock_bystring(pdb->tdb, keystr); - - /* - * Update the cache time FIRST ! Stops others even - * attempting to get the lock and doing this - * if the lpq takes a long time. - */ - - slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", printer_name); - tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL)); - - /* get the current queue using the appropriate interface */ - ZERO_STRUCT(status); - - qcount = (*(current_printif->queue_get))(snum, &queue, &status); - - DEBUG(3, ("%d job%s in queue for %s\n", qcount, (qcount != 1) ? - "s" : "", printer_name)); - - /* - any job in the internal database that is marked as spooled - and doesn't exist in the system queue is considered finished - and removed from the database - - any job in the system database but not in the internal database - is added as a unix job - - fill in any system job numbers as we go - */ - for (i=0; i<qcount; i++) { - uint32 jobid = print_parse_jobid(queue[i].fs_file); - - if (jobid == (uint32)-1) { - /* assume its a unix print job */ - print_unix_job(snum, &queue[i], jobid); - continue; - } - - /* we have an active SMB print job - update its status */ - pjob = print_job_find(snum, jobid); - if (!pjob) { - /* err, somethings wrong. Probably smbd was restarted - with jobs in the queue. All we can do is treat them - like unix jobs. Pity. */ - print_unix_job(snum, &queue[i], jobid); - continue; - } - - pjob->sysjob = queue[i].job; - pjob->status = queue[i].status; - - pjob_store(snum, jobid, pjob); - } - - /* now delete any queued entries that don't appear in the - system queue */ - tstruct.queue = queue; - tstruct.qcount = qcount; - tstruct.snum = snum; - tstruct.total_jobs = 0; - tstruct.lpq_time = time(NULL); - - tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct); - - SAFE_FREE(tstruct.queue); - - DEBUG(10,("print_queue_update: printer %s INFO/total_jobs = %d\n", - printer_name, tstruct.total_jobs )); - - tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs); - - get_queue_status(snum, &old_status); - if (old_status.qcount != qcount) - DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n", - old_status.qcount, qcount, printer_name )); - - /* store the new queue status structure */ - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printer_name); - key.dptr = keystr; - key.dsize = strlen(keystr); - - status.qcount = qcount; - data.dptr = (void *)&status; - data.dsize = sizeof(status); - tdb_store(pdb->tdb, key, data, TDB_REPLACE); - - /* - * Update the cache time again. We want to do this call - * as little as possible... - */ - - slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", printer_name); - tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL)); - - /* Delete our pid from the db. */ - set_updating_pid(printer_name, True); - release_print_db(pdb); -} - -/**************************************************************************** - Create/Update an entry in the print tdb that will allow us to send notify - updates only to interested smbd's. -****************************************************************************/ - -BOOL print_notify_register_pid(int snum) -{ - TDB_DATA data; - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - const char *printername; - uint32 mypid = (uint32)sys_getpid(); - BOOL ret = False; - size_t i; - - /* if (snum == -1), then the change notify request was - on a print server handle and we need to register on - all print queus */ - - if (snum == -1) - { - int num_services = lp_numservices(); - int idx; - - for ( idx=0; idx<num_services; idx++ ) { - if (lp_snum_ok(idx) && lp_print_ok(idx) ) - print_notify_register_pid(idx); - } - - return True; - } - else /* register for a specific printer */ - { - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - } - - if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n", - printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - /* Add ourselves and increase the refcount. */ - - for (i = 0; i < data.dsize; i += 8) { - if (IVAL(data.dptr,i) == mypid) { - uint32 new_refcount = IVAL(data.dptr, i+4) + 1; - SIVAL(data.dptr, i+4, new_refcount); - break; - } - } - - if (i == data.dsize) { - /* We weren't in the list. Realloc. */ - data.dptr = Realloc(data.dptr, data.dsize + 8); - if (!data.dptr) { - DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n", - printername)); - goto done; - } - data.dsize += 8; - SIVAL(data.dptr,data.dsize - 8,mypid); - SIVAL(data.dptr,data.dsize - 4,1); /* Refcount. */ - } - - /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to update pid \ -list for printer %s\n", printername)); - goto done; - } - - ret = True; - - done: - - tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Update an entry in the print tdb that will allow us to send notify - updates only to interested smbd's. -****************************************************************************/ - -BOOL print_notify_deregister_pid(int snum) -{ - TDB_DATA data; - struct tdb_print_db *pdb = NULL; - TDB_CONTEXT *tdb = NULL; - const char *printername; - uint32 mypid = (uint32)sys_getpid(); - size_t i; - BOOL ret = False; - - /* if ( snum == -1 ), we are deregister a print server handle - which means to deregister on all print queues */ - - if (snum == -1) - { - int num_services = lp_numservices(); - int idx; - - for ( idx=0; idx<num_services; idx++ ) { - if ( lp_snum_ok(idx) && lp_print_ok(idx) ) - print_notify_deregister_pid(idx); - } - - return True; - } - else /* deregister a specific printer */ - { - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - if (!pdb) - return False; - tdb = pdb->tdb; - } - - if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to lock \ -printer %s database\n", printername)); - if (pdb) - release_print_db(pdb); - return False; - } - - data = get_printer_notify_pid_list( tdb, printername, True ); - - /* Reduce refcount. Remove ourselves if zero. */ - - for (i = 0; i < data.dsize; ) { - if (IVAL(data.dptr,i) == mypid) { - uint32 refcount = IVAL(data.dptr, i+4); - - refcount--; - - if (refcount == 0) { - if (data.dsize - i > 8) - memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8); - data.dsize -= 8; - continue; - } - SIVAL(data.dptr, i+4, refcount); - } - - i += 8; - } - - if (data.dsize == 0) - SAFE_FREE(data.dptr); - - /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { - DEBUG(0,("print_notify_register_pid: Failed to update pid \ -list for printer %s\n", printername)); - goto done; - } - - ret = True; - - done: - - tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY); - if (pdb) - release_print_db(pdb); - SAFE_FREE(data.dptr); - return ret; -} - -/**************************************************************************** - Check if a jobid is valid. It is valid if it exists in the database. -****************************************************************************/ - -BOOL print_job_exists(int snum, uint32 jobid) -{ - struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum)); - BOOL ret; - - if (!pdb) - return False; - ret = tdb_exists(pdb->tdb, print_key(jobid)); - release_print_db(pdb); - return ret; -} - -/**************************************************************************** - Give the fd used for a jobid. -****************************************************************************/ - -int print_job_fd(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob) - return -1; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return -1; - return pjob->fd; -} - -/**************************************************************************** - Give the filename used for a jobid. - Only valid for the process doing the spooling and when the job - has not been spooled. -****************************************************************************/ - -char *print_job_fname(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob || pjob->spooled || pjob->pid != local_pid) - return NULL; - return pjob->filename; -} - - -/**************************************************************************** - Give the filename used for a jobid. - Only valid for the process doing the spooling and when the job - has not been spooled. -****************************************************************************/ - -NT_DEVICEMODE *print_job_devmode(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - - if ( !pjob ) - return NULL; - - return pjob->nt_devmode; -} - -/**************************************************************************** - Set the place in the queue for a job. -****************************************************************************/ - -BOOL print_job_set_place(int snum, uint32 jobid, int place) -{ - DEBUG(2,("print_job_set_place not implemented yet\n")); - return False; -} - -/**************************************************************************** - Set the name of a job. Only possible for owner. -****************************************************************************/ - -BOOL print_job_set_name(int snum, uint32 jobid, char *name) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob || pjob->pid != local_pid) - return False; - - fstrcpy(pjob->jobname, name); - return pjob_store(snum, jobid, pjob); -} - -/**************************************************************************** - Delete a print job - don't update queue. -****************************************************************************/ - -static BOOL print_job_delete1(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int result = 0; - - if (!pjob) - return False; - - /* - * If already deleting just return. - */ - - if (pjob->status == LPQ_DELETING) - return True; - - /* Hrm - we need to be able to cope with deleting a job before it - has reached the spooler. */ - - if (pjob->sysjob == -1) { - DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid)); - } - - /* Set the tdb entry to be deleting. */ - - pjob->status = LPQ_DELETING; - pjob_store(snum, jobid, pjob); - - if (pjob->spooled && pjob->sysjob != -1) - result = (*(current_printif->job_delete))(snum, pjob); - - /* Delete the tdb entry if the delete suceeded or the job hasn't - been spooled. */ - - if (result == 0) - pjob_delete(snum, jobid); - - return (result == 0); -} - -/**************************************************************************** - Return true if the current user owns the print job. -****************************************************************************/ - -static BOOL is_owner(struct current_user *user, int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - user_struct *vuser; - - if (!pjob || !user) - return False; - - if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - return strequal(pjob->user, vuser->user.smb_name); - } else { - return strequal(pjob->user, uidtoname(user->uid)); - } -} - -/**************************************************************************** - Delete a print job. -****************************************************************************/ - -BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - BOOL owner, deleted; - char *fname; - - *errcode = WERR_OK; - - owner = is_owner(user, snum, jobid); - - /* Check access against security descriptor or whether the user - owns their job. */ - - if (!owner && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("delete denied by security descriptor\n")); - *errcode = WERR_ACCESS_DENIED; - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - - return False; - } - - /* - * get the spooled filename of the print job - * if this works, then the file has not been spooled - * to the underlying print system. Just delete the - * spool file & return. - */ - - if ( (fname = print_job_fname( snum, jobid )) != NULL ) - { - /* remove the spool file */ - DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname )); - if ( unlink( fname ) == -1 ) { - *errcode = map_werror_from_unix(errno); - return False; - } - - return True; - } - - if (!print_job_delete1(snum, jobid)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - /* force update the database and say the delete failed if the - job still exists */ - - print_queue_update(snum); - - deleted = !print_job_exists(snum, jobid); - if ( !deleted ) - *errcode = WERR_ACCESS_DENIED; - - return deleted; -} - -/**************************************************************************** - Pause a job. -****************************************************************************/ - -BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret = -1; - - if (!pjob || !user) - return False; - - if (!pjob->spooled || pjob->sysjob == -1) - return False; - - if (!is_owner(user, snum, jobid) && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("pause denied by security descriptor\n")); - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - - *errcode = WERR_ACCESS_DENIED; - return False; - } - - /* need to pause the spooled entry */ - ret = (*(current_printif->job_pause))(snum, pjob); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_job_status(snum, jobid, JOB_STATUS_PAUSED); - - /* how do we tell if this succeeded? */ - - return True; -} - -/**************************************************************************** - Resume a job. -****************************************************************************/ - -BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret; - - if (!pjob || !user) - return False; - - if (!pjob->spooled || pjob->sysjob == -1) - return False; - - if (!is_owner(user, snum, jobid) && - !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { - DEBUG(3, ("resume denied by security descriptor\n")); - *errcode = WERR_ACCESS_DENIED; - - /* BEGIN_ADMIN_LOG */ - sys_adminlog( LOG_ERR, - "Permission denied-- user not allowed to delete, \ -pause, or resume print job. User name: %s. Printer name: %s.", - uidtoname(user->uid), PRINTERNAME(snum) ); - /* END_ADMIN_LOG */ - return False; - } - - ret = (*(current_printif->job_resume))(snum, pjob); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_job_status(snum, jobid, JOB_STATUS_QUEUED); - - return True; -} - -/**************************************************************************** - Write to a print file. -****************************************************************************/ - -int print_job_write(int snum, uint32 jobid, const char *buf, int size) -{ - int return_code; - struct printjob *pjob = print_job_find(snum, jobid); - - if (!pjob) - return -1; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return -1; - - return_code = write(pjob->fd, buf, size); - if (return_code>0) { - pjob->size += size; - pjob_store(snum, jobid, pjob); - } - return return_code; -} - -/**************************************************************************** - Check if the print queue has been updated recently enough. -****************************************************************************/ - -static BOOL print_cache_expired(int snum) -{ - fstring key; - time_t last_qscan_time, time_now = time(NULL); - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - - if (!pdb) - return False; - - slprintf(key, sizeof(key), "CACHE/%s", printername); - last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key); - - /* - * Invalidate the queue for 3 reasons. - * (1). last queue scan time == -1. - * (2). Current time - last queue scan time > allowed cache time. - * (3). last queue scan time > current time + MAX_CACHE_VALID_TIME (1 hour by default). - * This last test picks up machines for which the clock has been moved - * forward, an lpq scan done and then the clock moved back. Otherwise - * that last lpq scan would stay around for a loooong loooong time... :-). JRA. - */ - - if (last_qscan_time == ((time_t)-1) || (time_now - last_qscan_time) >= lp_lpqcachetime() || - last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) { - DEBUG(3, ("print cache expired for queue %s \ -(last_qscan_time = %d, time now = %d, qcachetime = %d)\n", printername, - (int)last_qscan_time, (int)time_now, (int)lp_lpqcachetime() )); - release_print_db(pdb); - return True; - } - release_print_db(pdb); - return False; -} - -/**************************************************************************** - Get the queue status - do not update if db is out of date. -****************************************************************************/ - -static int get_queue_status(int snum, print_status_struct *status) -{ - fstring keystr; - TDB_DATA data, key; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - int len; - - if (!pdb) - return 0; - - if (status) { - ZERO_STRUCTP(status); - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printername); - key.dptr = keystr; - key.dsize = strlen(keystr); - data = tdb_fetch(pdb->tdb, key); - if (data.dptr) { - if (data.dsize == sizeof(print_status_struct)) - memcpy(status, data.dptr, sizeof(print_status_struct)); - SAFE_FREE(data.dptr); - } - } - len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs"); - release_print_db(pdb); - return (len == -1 ? 0 : len); -} - -/**************************************************************************** - Determine the number of jobs in a queue. -****************************************************************************/ - -int print_queue_length(int snum, print_status_struct *pstatus) -{ - print_status_struct status; - int len; - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* also fetch the queue status */ - memset(&status, 0, sizeof(status)); - len = get_queue_status(snum, &status); - - if (pstatus) - *pstatus = status; - - return len; -} - -/*************************************************************************** - Allocate a jobid. Hold the lock for as short a time as possible. -***************************************************************************/ - -static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *printername, uint32 *pjobid) -{ - int i; - uint32 jobid; - - *pjobid = (uint32)-1; - - for (i = 0; i < 3; i++) { - /* Lock the database - only wait 20 seconds. */ - if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) { - DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", printername )); - return False; - } - - if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) { - if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) { - DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n", - printername )); - return False; - } - jobid = 0; - } - - jobid = NEXT_JOBID(jobid); - - if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) { - DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n")); - tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); - return False; - } - - /* We've finished with the INFO/nextjob lock. */ - tdb_unlock_bystring(pdb->tdb, "INFO/nextjob"); - - if (!print_job_exists(snum, jobid)) - break; - } - - if (i > 2) { - DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n", - printername )); - /* Probably full... */ - errno = ENOSPC; - return False; - } - - /* Store a dummy placeholder. */ - { - TDB_DATA dum; - dum.dptr = NULL; - dum.dsize = 0; - if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) { - DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n", - jobid )); - return False; - } - } - - *pjobid = jobid; - return True; -} - -/*************************************************************************** - Start spooling a job - return the jobid. -***************************************************************************/ - -uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode ) -{ - uint32 jobid; - char *path; - struct printjob pjob; - user_struct *vuser; - const char *printername = lp_const_servicename(snum); - struct tdb_print_db *pdb = get_print_db_byname(printername); - int njobs; - - errno = 0; - - if (!pdb) - return (uint32)-1; - - if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) { - DEBUG(3, ("print_job_start: job start denied by security descriptor\n")); - release_print_db(pdb); - return (uint32)-1; - } - - if (!print_time_access_check(snum)) { - DEBUG(3, ("print_job_start: job start denied by time check\n")); - release_print_db(pdb); - return (uint32)-1; - } - - path = lp_pathname(snum); - - /* see if we have sufficient disk space */ - if (lp_minprintspace(snum)) { - SMB_BIG_UINT dspace, dsize; - if (sys_fsusage(path, &dspace, &dsize) == 0 && - dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) { - DEBUG(3, ("print_job_start: disk space check failed.\n")); - release_print_db(pdb); - errno = ENOSPC; - return (uint32)-1; - } - } - - /* for autoloaded printers, check that the printcap entry still exists */ - if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum), NULL)) { - DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) )); - release_print_db(pdb); - errno = ENOENT; - return (uint32)-1; - } - - /* Insure the maximum queue size is not violated */ - if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) { - DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n", - printername, njobs, lp_maxprintjobs(snum) )); - release_print_db(pdb); - errno = ENOSPC; - return (uint32)-1; - } - - DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n", - printername, njobs, lp_maxprintjobs(snum) )); - - if (!allocate_print_jobid(pdb, snum, printername, &jobid)) - goto fail; - - /* create the database entry */ - - ZERO_STRUCT(pjob); - - pjob.pid = local_pid; - pjob.sysjob = -1; - pjob.fd = -1; - pjob.starttime = time(NULL); - pjob.status = LPQ_SPOOLING; - pjob.size = 0; - pjob.spooled = False; - pjob.smbjob = True; - pjob.nt_devmode = nt_devmode; - - fstrcpy(pjob.jobname, jobname); - - if ((vuser = get_valid_user_struct(user->vuid)) != NULL) { - fstrcpy(pjob.user, vuser->user.smb_name); - } else { - fstrcpy(pjob.user, uidtoname(user->uid)); - } - - fstrcpy(pjob.queuename, lp_const_servicename(snum)); - - /* we have a job entry - now create the spool file */ - slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", - path, PRINT_SPOOL_PREFIX, (unsigned int)jobid); - pjob.fd = smb_mkstemp(pjob.filename); - - if (pjob.fd == -1) { - if (errno == EACCES) { - /* Common setup error, force a report. */ - DEBUG(0, ("print_job_start: insufficient permissions \ -to open spool file %s.\n", pjob.filename)); - } else { - /* Normal case, report at level 3 and above. */ - DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename)); - DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno))); - } - goto fail; - } - - pjob_store(snum, jobid, &pjob); - - /* Ensure we keep a rough count of the number of total jobs... */ - tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1); - - release_print_db(pdb); - - return jobid; - - fail: - if (jobid != -1) - pjob_delete(snum, jobid); - - release_print_db(pdb); - - DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) )); - return (uint32)-1; -} - -/**************************************************************************** - Update the number of pages spooled to jobid -****************************************************************************/ - -void print_job_endpage(int snum, uint32 jobid) -{ - struct printjob *pjob = print_job_find(snum, jobid); - if (!pjob) - return; - /* don't allow another process to get this info - it is meaningless */ - if (pjob->pid != local_pid) - return; - - pjob->page_count++; - pjob_store(snum, jobid, pjob); -} - -/**************************************************************************** - Print a file - called on closing the file. This spools the job. - If normal close is false then we're tearing down the jobs - treat as an - error. -****************************************************************************/ - -BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close) -{ - struct printjob *pjob = print_job_find(snum, jobid); - int ret; - SMB_STRUCT_STAT sbuf; - - if (!pjob) - return False; - - if (pjob->spooled || pjob->pid != local_pid) - return False; - - if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) { - pjob->size = sbuf.st_size; - close(pjob->fd); - pjob->fd = -1; - } else { - - /* - * Not a normal close or we couldn't stat the job file, - * so something has gone wrong. Cleanup. - */ - close(pjob->fd); - pjob->fd = -1; - DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid )); - goto fail; - } - - /* Technically, this is not quite right. If the printer has a separator - * page turned on, the NT spooler prints the separator page even if the - * print job is 0 bytes. 010215 JRR */ - if (pjob->size == 0 || pjob->status == LPQ_DELETING) { - /* don't bother spooling empty files or something being deleted. */ - DEBUG(5,("print_job_end: canceling spool of %s (%s)\n", - pjob->filename, pjob->size ? "deleted" : "zero length" )); - unlink(pjob->filename); - pjob_delete(snum, jobid); - return True; - } - - ret = (*(current_printif->job_submit))(snum, pjob); - - if (ret) - goto fail; - - /* The print job has been sucessfully handed over to the back-end */ - - pjob->spooled = True; - pjob->status = LPQ_QUEUED; - pjob_store(snum, jobid, pjob); - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - return True; - -fail: - - /* The print job was not succesfully started. Cleanup */ - /* Still need to add proper error return propagation! 010122:JRR */ - unlink(pjob->filename); - pjob_delete(snum, jobid); - return False; -} - -/**************************************************************************** - Utility fn to enumerate the print queue. -****************************************************************************/ - -static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_struct *ts = (struct traverse_struct *)state; - struct printjob pjob; - int i; - uint32 jobid; - - /* sanity checks */ - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - free_nt_devicemode( &pjob.nt_devmode ); - - /* maybe it isn't for this queue */ - if (ts->snum != lp_servicenumber(pjob.queuename)) - return 0; - - if (ts->qcount >= ts->maxcount) - return 0; - - i = ts->qcount; - - ts->queue[i].job = jobid; - ts->queue[i].size = pjob.size; - ts->queue[i].page_count = pjob.page_count; - ts->queue[i].status = pjob.status; - ts->queue[i].priority = 1; - ts->queue[i].time = pjob.starttime; - fstrcpy(ts->queue[i].fs_user, pjob.user); - fstrcpy(ts->queue[i].fs_file, pjob.jobname); - - ts->qcount++; - - return 0; -} - -struct traverse_count_struct { - int snum, count; -}; - -/**************************************************************************** - Utility fn to count the number of entries in the print queue. -****************************************************************************/ - -static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) -{ - struct traverse_count_struct *ts = (struct traverse_count_struct *)state; - struct printjob pjob; - uint32 jobid; - - /* sanity checks */ - - if ( key.dsize != sizeof(jobid) ) - return 0; - - memcpy(&jobid, key.dptr, sizeof(jobid)); - - if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 ) - return 0; - - free_nt_devicemode( &pjob.nt_devmode ); - - /* maybe it isn't for this queue - this cannot happen with the tdb/printer code. JRA */ - if (ts->snum != lp_servicenumber(pjob.queuename)) - return 0; - - ts->count++; - - return 0; -} - -/**************************************************************************** - Sort print jobs by submittal time. -****************************************************************************/ - -static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2) -{ - /* Silly cases */ - - if (!j1 && !j2) - return 0; - if (!j1) - return -1; - if (!j2) - return 1; - - /* Sort on job start time */ - - if (j1->time == j2->time) - return 0; - return (j1->time > j2->time) ? 1 : -1; -} - -/**************************************************************************** - Get a printer queue listing. - set queue = NULL and status = NULL if you just want to update the cache -****************************************************************************/ - -int print_queue_status(int snum, - print_queue_struct **queue, - print_status_struct *status) -{ - struct traverse_struct tstruct; - struct traverse_count_struct tsc; - fstring keystr; - TDB_DATA data, key; - const char *printername; - struct tdb_print_db *pdb; - - /* make sure the database is up to date */ - - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* return if we are done */ - - if ( !queue || !status ) - return 0; - - *queue = NULL; - printername = lp_const_servicename(snum); - pdb = get_print_db_byname(printername); - - if (!pdb) - return 0; - - /* - * Fetch the queue status. We must do this first, as there may - * be no jobs in the queue. - */ - ZERO_STRUCTP(status); - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printername); - key.dptr = keystr; - key.dsize = strlen(keystr); - data = tdb_fetch(pdb->tdb, key); - if (data.dptr) { - if (data.dsize == sizeof(*status)) { - memcpy(status, data.dptr, sizeof(*status)); - } - SAFE_FREE(data.dptr); - } - - /* - * Now, fetch the print queue information. We first count the number - * of entries, and then only retrieve the queue if necessary. - */ - tsc.count = 0; - tsc.snum = snum; - - tdb_traverse(pdb->tdb, traverse_count_fn_queue, (void *)&tsc); - - if (tsc.count == 0) { - release_print_db(pdb); - return 0; - } - - /* Allocate the queue size. */ - if ((tstruct.queue = (print_queue_struct *) - malloc(sizeof(print_queue_struct)*tsc.count)) == NULL) { - release_print_db(pdb); - return 0; - } - - /* - * Fill in the queue. - * We need maxcount as the queue size may have changed between - * the two calls to tdb_traverse. - */ - tstruct.qcount = 0; - tstruct.maxcount = tsc.count; - tstruct.snum = snum; - - tdb_traverse(pdb->tdb, traverse_fn_queue, (void *)&tstruct); - release_print_db(pdb); - - /* Sort the queue by submission time otherwise they are displayed - in hash order. */ - - qsort(tstruct.queue, tstruct.qcount, sizeof(print_queue_struct), - QSORT_CAST printjob_comp); - - *queue = tstruct.queue; - return tstruct.qcount; -} - -/**************************************************************************** - Pause a queue. -****************************************************************************/ - -BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode) -{ - int ret; - - if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - ret = (*(current_printif->queue_pause))(snum); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* force update the database */ - print_cache_flush(snum); - - /* Send a printer notify message */ - - notify_printer_status(snum, PRINTER_STATUS_PAUSED); - - return True; -} - -/**************************************************************************** - Resume a queue. -****************************************************************************/ - -BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode) -{ - int ret; - - if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { - *errcode = WERR_ACCESS_DENIED; - return False; - } - - ret = (*(current_printif->queue_resume))(snum); - - if (ret != 0) { - *errcode = WERR_INVALID_PARAM; - return False; - } - - /* make sure the database is up to date */ - if (print_cache_expired(snum)) - print_queue_update(snum); - - /* Send a printer notify message */ - - notify_printer_status(snum, PRINTER_STATUS_OK); - - return True; -} - -/**************************************************************************** - Purge a queue - implemented by deleting all jobs that we can delete. -****************************************************************************/ - -BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode) -{ - print_queue_struct *queue; - print_status_struct status; - int njobs, i; - BOOL can_job_admin; - - /* Force and update so the count is accurate (i.e. not a cached count) */ - print_queue_update(snum); - - can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER); - njobs = print_queue_status(snum, &queue, &status); - - for (i=0;i<njobs;i++) { - BOOL owner = is_owner(user, snum, queue[i].job); - - if (owner || can_job_admin) { - print_job_delete1(snum, queue[i].job); - } - } - - SAFE_FREE(queue); - - return True; -} diff --git a/source4/printing/printing_db.c b/source4/printing/printing_db.c deleted file mode 100644 index 0aa8dfafa5..0000000000 --- a/source4/printing/printing_db.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0 - printing backend routines - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 2002 - - 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 "printing.h" - -static struct tdb_print_db *print_db_head; - -/**************************************************************************** - Function to find or create the printer specific job tdb given a printername. - Limits the number of tdb's open to MAX_PRINT_DBS_OPEN. -****************************************************************************/ - -struct tdb_print_db *get_print_db_byname(const char *printername) -{ - struct tdb_print_db *p = NULL, *last_entry = NULL; - int num_open = 0; - pstring printdb_path; - BOOL done_become_root = False; - - for (p = print_db_head, last_entry = print_db_head; p; p = p->next) { - /* Ensure the list terminates... JRA. */ - SMB_ASSERT(p->next != print_db_head); - - if (p->tdb && strequal(p->printer_name, printername)) { - DLIST_PROMOTE(print_db_head, p); - p->ref_count++; - return p; - } - num_open++; - last_entry = p; - } - - /* Not found. */ - if (num_open >= MAX_PRINT_DBS_OPEN) { - /* Try and recycle the last entry. */ - DLIST_PROMOTE(print_db_head, last_entry); - - for (p = print_db_head; p; p = p->next) { - if (p->ref_count) - continue; - if (p->tdb) { - if (tdb_close(print_db_head->tdb)) { - DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n", - print_db_head->printer_name )); - return NULL; - } - } - p->tdb = NULL; - p->ref_count = 0; - memset(p->printer_name, '\0', sizeof(p->printer_name)); - break; - } - if (p) { - DLIST_PROMOTE(print_db_head, p); - p = print_db_head; - } - } - - if (!p) { - /* Create one. */ - p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db)); - if (!p) { - DEBUG(0,("get_print_db: malloc fail !\n")); - return NULL; - } - ZERO_STRUCTP(p); - DLIST_ADD(print_db_head, p); - } - - pstrcpy(printdb_path, lock_path("printing/")); - pstrcat(printdb_path, printername); - pstrcat(printdb_path, ".tdb"); - - if (geteuid() != 0) { - become_root(); - done_become_root = True; - } - - p->tdb = tdb_open_log(printdb_path, 5000, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - - if (done_become_root) - unbecome_root(); - - if (!p->tdb) { - DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n", - printdb_path )); - DLIST_REMOVE(print_db_head, p); - SAFE_FREE(p); - return NULL; - } - fstrcpy(p->printer_name, printername); - p->ref_count++; - return p; -} - -/*************************************************************************** - Remove a reference count. -****************************************************************************/ - -void release_print_db( struct tdb_print_db *pdb) -{ - pdb->ref_count--; - SMB_ASSERT(pdb->ref_count >= 0); -} - -/*************************************************************************** - Close all open print db entries. -****************************************************************************/ - -void close_all_print_db(void) -{ - struct tdb_print_db *p = NULL, *next_p = NULL; - - for (p = print_db_head; p; p = next_p) { - next_p = p->next; - - if (p->tdb) - tdb_close(p->tdb); - DLIST_REMOVE(print_db_head, p); - ZERO_STRUCTP(p); - SAFE_FREE(p); - } -} - - -/**************************************************************************** - Fetch and clean the pid_t record list for all pids interested in notify - messages. data needs freeing on exit. -****************************************************************************/ - -TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, BOOL cleanlist) -{ - TDB_DATA data; - size_t i; - - ZERO_STRUCT(data); - - data = tdb_fetch_by_string( tdb, NOTIFY_PID_LIST_KEY ); - - if (!data.dptr) { - ZERO_STRUCT(data); - return data; - } - - if (data.dsize % 8) { - DEBUG(0,("get_printer_notify_pid_list: Size of record for printer %s not a multiple of 8 !\n", printer_name )); - tdb_delete_by_string(tdb, NOTIFY_PID_LIST_KEY ); - SAFE_FREE(data.dptr); - ZERO_STRUCT(data); - return data; - } - - if (!cleanlist) - return data; - - /* - * Weed out all dead entries. - */ - - for( i = 0; i < data.dsize; i += 8) { - pid_t pid = (pid_t)IVAL(data.dptr, i); - - if (pid == sys_getpid()) - continue; - - /* Entry is dead if process doesn't exist or refcount is zero. */ - - while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) { - - /* Refcount == zero is a logic error and should never happen. */ - if (IVAL(data.dptr, i + 4) == 0) { - DEBUG(0,("get_printer_notify_pid_list: Refcount == 0 for pid = %u printer %s !\n", - (unsigned int)pid, printer_name )); - } - - if (data.dsize - i > 8) - memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8); - data.dsize -= 8; - } - } - - return data; -} - - diff --git a/source4/smbwrapper/PORTING b/source4/smbwrapper/PORTING deleted file mode 100644 index 884246d078..0000000000 --- a/source4/smbwrapper/PORTING +++ /dev/null @@ -1,77 +0,0 @@ -This describes how to port the smbwrapper portion of Samba to a new -unix-like platform. Note that porting smbwrapper is considerably -harder than porting Samba, for Samba you generally just need to run -configure and recompile whereas for smbwrapper some extra effort is -generally required. - - -STEP 1 ------- - -The first step is to work out how to create a shared library on your -OS and how to compile C code to produce position independent object -files (PIC files). You shoud be able to find this information in the -man pages for your compiler and loader (ld). Then modify configure.in -to give that information to Samba. - - -STEP 2 ------- - -The next step is to work out how to preload shared objects. On many -systems this is done using a LD_PRELOAD environment variable. On -others (shc as IRIX) it may use a _RTL_LIST variable. - -To make sure it works I suggest you create two C files like this: - -/* first C file */ -main() -{ - unlink("foo.txt"); -} - -/* second C file */ -#include <stdio.h> - -int unlink(char *fname) -{ - fprintf(stderr,"unlink(%s) called\n",fname); -} - - -then compile the first as an ordinary C program and the second as a -shared library. Then use LD_PRELOAD to preload the resulting shared -library. Then run the first program. It should print "unlink(foo.txt) -called". If it doesn't then consult your man pages till you get it -right. - -Once you work this out then edit smbwrapper/smbsh.in and add a section -if necessary to correctly set the necessary preload options for your -OS. - - -STEP 3 ------- - -The next step is to work out how to make direct system calls. On most -machines this will work without any source code changes to -smbwrapper. To test that it does work create the following C program: - -#include <sys/syscall.h> -main() -{ - syscall(SYS_write, 1, "hello world\n", 12); -} - -and try to compile/run it. If it produces "hello world" then syscall() -works as expected. If not then work out what needs to be changed and -then make that change in realcalls.h. For example, on IRIX 6.4 the -system call numbers are wrong and need to be fixed up by getting an -offset right. - - -STEP 4 ------- - -Try compiling smbwrapper! Then test it. Then debug it. Simple really :) - diff --git a/source4/smbwrapper/README b/source4/smbwrapper/README deleted file mode 100644 index 8d5c376f82..0000000000 --- a/source4/smbwrapper/README +++ /dev/null @@ -1,94 +0,0 @@ -This is a prelodable shared library that provides SMB client services -for existing executables. Using this you can simulate a smb -filesystem. - -*** This is code under development. Some things don't work yet *** - -Currently this code has been tested on: - -- Linux 2.0 with glibc2 (RH5.1) -- Linux 2.1 with glibc2 -- Solaris 2.5.1 with gcc -- Solaris 2.6 with gcc -- SunOS 4.1.3 with gcc -- IRIX 6.4 with cc -- OSF1 with gcc - - -It probably won't run on other systems without some porting. If you -have a different system then see the file PORTING. - -To use it you need to do this: - -1) build smbwrapper.so using the command "make smbwrapper" -3) run smbsh - -You will be asked for a username and password. After that you will be -returned to a shell prompt. It is actually a subshell running with -smbwrapper enabled. - -Now try to access /smb/SERVER for some SMB server name and see what -happens. If you use the -W option to set your workgroup or have -workgroup set in your smb.conf then listing /smb/ should list all SMB -servers in your workgroup. - - -OPTIONS -------- - --U username - specify the username and optional password (as user%password) - --d debug level - This is an integer that controls the internal debug level of smbw. It - defaults to 0, which means no debug info. - --l logfile - The place where smbw debug logs are put. If this is not set then - stderr is used. - --P prefix - The root of the SMB filesystem. This defaults to /smb/ but you can - set it to any name you like. - --W workgroup - This is the workgroup used for browsing (ie. listing machines in the - /smb/ directory). It defaults to the one set in smb.conf. - --R resolve order - This allows you to override the setting of the name resolve order - from smb.conf - - -ATTRIBUTE MAPPING ------------------ - -smbwrapper does an inverse attribute maping to what Samba does. This -means that the archive bit appears as the user execute bit, the system -bit appears as the group execute bit and the hidden bit appears as the -other execute bit. You can control these with chmod. The mapping can -be enabled an disabled using the normal smb.conf controls (ie. "map -archive", "map system" and "map hidden"). - -Read-only files appear as non-writeable by everyone. Writeable files -appear as writeable by the current user. - - -WHAT WORKS ----------- - -Things that I have tried and do seem to work include: - - emacs, tar, ls, cmp, cp, rsync, du, cat, rm, mv, less, more, wc, head, - tail, bash, tcsh, mkdir, rmdir, vim, xedit, diff - -things that I know don't work: - - anything executing from the share - anything that uses mmap - redirection within shells to smbsh files - -If you want to help with the development of this code then join the -samba-technical mailing list. - - diff --git a/source4/smbwrapper/realcalls.c b/source4/smbwrapper/realcalls.c deleted file mode 100644 index b64f4a43db..0000000000 --- a/source4/smbwrapper/realcalls.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions for calls that syscall() can't do - Copyright (C) Andrew Tridgell 1998 - - 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 "realcalls.h" - -#ifdef REPLACE_UTIME -int real_utime(const char *name, struct utimbuf *buf) -{ - struct timeval tv[2]; - - tv[0].tv_sec = buf->actime; - tv[0].tv_usec = 0; - tv[1].tv_sec = buf->modtime; - tv[1].tv_usec = 0; - - return real_utimes(name, &tv[0]); -} -#endif - -#ifdef REPLACE_UTIMES -int real_utimes(const char *name, struct timeval tv[2]) -{ - struct utimbuf buf; - - buf.actime = tv[0].tv_sec; - buf.modtime = tv[1].tv_sec; - - return real_utime(name, &buf); -} -#endif diff --git a/source4/smbwrapper/realcalls.h b/source4/smbwrapper/realcalls.h deleted file mode 100644 index 6c230dba05..0000000000 --- a/source4/smbwrapper/realcalls.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - Unix SMB/CIFS implementation. - defintions of syscall entries - Copyright (C) Andrew Tridgell 1998 - - 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. -*/ - -#if HAVE_SYS_SYSCALL_H -#include <sys/syscall.h> -#elif HAVE_SYSCALL_H -#include <syscall.h> -#endif - -#ifdef IRIX -/* amazingly, IRIX gets its own syscall numbers wrong! */ -#ifdef SYSVoffset -#if (SYSVoffset == 1) -#undef SYSVoffset -#define SYSVoffset 1000 -#endif -#endif -#endif - -/* this file is partly derived from zlibc by Alain Knaff */ - -#define real_access(fn, mode) (syscall(SYS_access, (fn), (mode))) -#define real_chdir(fn) (syscall(SYS_chdir, (fn))) -#define real_chmod(fn, mode) (syscall(SYS_chmod,(fn), (mode))) -#define real_chown(fn, owner, group) (syscall(SYS_chown,(fn),(owner),(group))) - -#ifdef SYS_getdents -#define real_getdents(fd, dirp, count) (syscall(SYS_getdents, (fd), (dirp), (count))) -#endif - -#define real_link(fn1, fn2) (syscall(SYS_link, (fn1), (fn2))) - -#define real_open(fn,flags,mode) (syscall(SYS_open, (fn), (flags), (mode))) - -#ifdef SYS_open64 -#define real_open64(fn,flags,mode) (syscall(SYS_open64, (fn), (flags), (mode))) -#elif HAVE__OPEN64 -#define real_open64(fn,flags,mode) (_open64(fn,flags,mode)) -#define NO_OPEN64_ALIAS -#elif HAVE___OPEN64 -#define real_open64(fn,flags,mode) (__open64(fn,flags,mode)) -#define NO_OPEN64_ALIAS -#endif - -#ifdef HAVE__FORK -#define real_fork() (_fork()) -#elif HAVE___FORK -#define real_fork() (__fork()) -#elif SYS_fork -#define real_fork() (syscall(SYS_fork)) -#endif - -#ifdef HAVE__OPENDIR -#define real_opendir(fn) (_opendir(fn)) -#elif SYS_opendir -#define real_opendir(fn) (syscall(SYS_opendir,(fn))) -#elif HAVE___OPENDIR -#define real_opendir(fn) (__opendir(fn)) -#endif - -#ifdef HAVE__READDIR -#define real_readdir(d) (_readdir(d)) -#elif HAVE___READDIR -#define real_readdir(d) (__readdir(d)) -#elif SYS_readdir -#define real_readdir(d) (syscall(SYS_readdir,(d))) -#endif - -#ifdef HAVE__CLOSEDIR -#define real_closedir(d) (_closedir(d)) -#elif SYS_closedir -#define real_closedir(d) (syscall(SYS_closedir,(d))) -#elif HAVE___CLOSEDIR -#define real_closedir(d) (__closedir(d)) -#endif - -#ifdef HAVE__SEEKDIR -#define real_seekdir(d,l) (_seekdir(d,l)) -#elif SYS_seekdir -#define real_seekdir(d,l) (syscall(SYS_seekdir,(d),(l))) -#elif HAVE___SEEKDIR -#define real_seekdir(d,l) (__seekdir(d,l)) -#else -#define NO_SEEKDIR_WRAPPER -#endif - -#ifdef HAVE__TELLDIR -#define real_telldir(d) (_telldir(d)) -#elif SYS_telldir -#define real_telldir(d) (syscall(SYS_telldir,(d))) -#elif HAVE___TELLDIR -#define real_telldir(d) (__telldir(d)) -#endif - -#ifdef HAVE__DUP -#define real_dup(d) (_dup(d)) -#elif SYS_dup -#define real_dup(d) (syscall(SYS_dup,(d))) -#elif HAVE___DUP -#define real_dup(d) (__dup(d)) -#endif - -#ifdef HAVE__DUP2 -#define real_dup2(d1,d2) (_dup2(d1,d2)) -#elif SYS_dup2 -#define real_dup2(d1,d2) (syscall(SYS_dup2,(d1),(d2))) -#elif HAVE___DUP2 -#define real_dup2(d1,d2) (__dup2(d1,d2)) -#endif - -#ifdef HAVE__GETCWD -#define real_getcwd(b,s) ((char *)_getcwd(b,s)) -#elif SYS_getcwd -#define real_getcwd(b,s) ((char *)syscall(SYS_getcwd,(b),(s))) -#elif HAVE___GETCWD -#define real_getcwd(b,s) ((char *)__getcwd(b,s)) -#endif - -#ifdef HAVE__STAT -#define real_stat(fn,st) (_stat(fn,st)) -#elif SYS_stat -#define real_stat(fn,st) (syscall(SYS_stat,(fn),(st))) -#elif HAVE___STAT -#define real_stat(fn,st) (__stat(fn,st)) -#endif - -#ifdef HAVE__LSTAT -#define real_lstat(fn,st) (_lstat(fn,st)) -#elif SYS_lstat -#define real_lstat(fn,st) (syscall(SYS_lstat,(fn),(st))) -#elif HAVE___LSTAT -#define real_lstat(fn,st) (__lstat(fn,st)) -#endif - -#ifdef HAVE__FSTAT -#define real_fstat(fd,st) (_fstat(fd,st)) -#elif SYS_fstat -#define real_fstat(fd,st) (syscall(SYS_fstat,(fd),(st))) -#elif HAVE___FSTAT -#define real_fstat(fd,st) (__fstat(fd,st)) -#endif - -#if defined(HAVE_SYS_ACL_H) && defined(HAVE__ACL) -#define real_acl(fn,cmd,n,buf) (_acl(fn,cmd,n,buf)) -#elif SYS_acl -#define real_acl(fn,cmd,n,buf) (syscall(SYS_acl,(fn),(cmd),(n),(buf))) -#elif HAVE___ACL -#define real_acl(fn,cmd,n,buf) (__acl(fn,cmd,n,buf)) -#else -#define NO_ACL_WRAPPER -#endif - -#ifdef HAVE__FACL -#define real_facl(fd,cmd,n,buf) (_facl(fd,cmd,n,buf)) -#elif SYS_facl -#define real_facl(fd,cmd,n,buf) (syscall(SYS_facl,(fd),(cmd),(n),(buf))) -#elif HAVE___FACL -#define real_facl(fd,cmd,n,buf) (__facl(fd,cmd,n,buf)) -#else -#define NO_FACL_WRAPPER -#endif - - -#ifdef HAVE__STAT64 -#define real_stat64(fn,st) (_stat64(fn,st)) -#elif HAVE___STAT64 -#define real_stat64(fn,st) (__stat64(fn,st)) -#endif - -#ifdef HAVE__LSTAT64 -#define real_lstat64(fn,st) (_lstat64(fn,st)) -#elif HAVE___LSTAT64 -#define real_lstat64(fn,st) (__lstat64(fn,st)) -#endif - -#ifdef HAVE__FSTAT64 -#define real_fstat64(fd,st) (_fstat64(fd,st)) -#elif HAVE___FSTAT64 -#define real_fstat64(fd,st) (__fstat64(fd,st)) -#endif - -#ifdef HAVE__READDIR64 -#define real_readdir64(d) (_readdir64(d)) -#elif HAVE___READDIR64 -#define real_readdir64(d) (__readdir64(d)) -#endif - -#ifdef HAVE__LLSEEK -#define real_llseek(fd,ofs,whence) (_llseek(fd,ofs,whence)) -#elif HAVE___LLSEEK -#define real_llseek(fd,ofs,whence) (__llseek(fd,ofs,whence)) -#elif HAVE___SYS_LLSEEK -#define real_llseek(fd,ofs,whence) (__sys_llseek(fd,ofs,whence)) -#endif - - -#ifdef HAVE__PREAD -#define real_pread(fd,buf,size,ofs) (_pread(fd,buf,size,ofs)) -#elif HAVE___PREAD -#define real_pread(fd,buf,size,ofs) (__pread(fd,buf,size,ofs)) -#endif - -#ifdef HAVE__PREAD64 -#define real_pread64(fd,buf,size,ofs) (_pread64(fd,buf,size,ofs)) -#elif HAVE___PREAD64 -#define real_pread64(fd,buf,size,ofs) (__pread64(fd,buf,size,ofs)) -#endif - -#ifdef HAVE__PWRITE -#define real_pwrite(fd,buf,size,ofs) (_pwrite(fd,buf,size,ofs)) -#elif HAVE___PWRITE -#define real_pwrite(fd,buf,size,ofs) (__pwrite(fd,buf,size,ofs)) -#endif - -#ifdef HAVE__PWRITE64 -#define real_pwrite64(fd,buf,size,ofs) (_pwrite64(fd,buf,size,ofs)) -#elif HAVE___PWRITE64 -#define real_pwrite64(fd,buf,size,ofs) (__pwrite64(fd,buf,size,ofs)) -#endif - - -#define real_readlink(fn,buf,len) (syscall(SYS_readlink, (fn), (buf), (len))) -#define real_rename(fn1, fn2) (syscall(SYS_rename, (fn1), (fn2))) -#define real_symlink(fn1, fn2) (syscall(SYS_symlink, (fn1), (fn2))) -#define real_read(fd, buf, count ) (syscall(SYS_read, (fd), (buf), (count))) -#define real_lseek(fd, offset, whence) (syscall(SYS_lseek, (fd), (offset), (whence))) -#define real_write(fd, buf, count ) (syscall(SYS_write, (fd), (buf), (count))) -#define real_close(fd) (syscall(SYS_close, (fd))) -#define real_fchdir(fd) (syscall(SYS_fchdir, (fd))) -#define real_fcntl(fd,cmd,arg) (syscall(SYS_fcntl, (fd), (cmd), (arg))) -#define real_symlink(fn1, fn2) (syscall(SYS_symlink, (fn1), (fn2))) -#define real_unlink(fn) (syscall(SYS_unlink, (fn))) -#define real_rmdir(fn) (syscall(SYS_rmdir, (fn))) -#define real_mkdir(fn, mode) (syscall(SYS_mkdir, (fn), (mode))) - -#ifdef SYS_utime -#define real_utime(fn, buf) (syscall(SYS_utime, (fn), (buf))) -#else -#define REPLACE_UTIME 1 -#endif - -#ifdef SYS_utimes -#define real_utimes(fn, buf) (syscall(SYS_utimes, (fn), (buf))) -#else -#define REPLACE_UTIMES 1 -#endif diff --git a/source4/smbwrapper/shared.c b/source4/smbwrapper/shared.c deleted file mode 100644 index b4cfcf7148..0000000000 --- a/source4/smbwrapper/shared.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - shared variables - Copyright (C) Andrew Tridgell 1998 - - 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" - -static int shared_fd; -static char *variables; -static int shared_size; - -/***************************************************** -setup the shared area -*******************************************************/ -void smbw_setup_shared(void) -{ - int fd; - pstring name, s; - - slprintf(name,sizeof(name)-1, "%s/smbw.XXXXXX",tmpdir()); - - fd = smb_mkstemp(name); - - if (fd == -1) goto failed; - - unlink(name); - - shared_fd = set_maxfiles(SMBW_MAX_OPEN); - - while (shared_fd && dup2(fd, shared_fd) != shared_fd) shared_fd--; - - if (shared_fd == 0) goto failed; - - close(fd); - - DEBUG(4,("created shared_fd=%d\n", shared_fd)); - - slprintf(s,sizeof(s)-1,"%d", shared_fd); - - setenv("SMBW_HANDLE", s, 1); - - return; - - failed: - perror("Failed to setup shared variable area "); - exit(1); -} - -static int locked; - -/***************************************************** -lock the shared variable area -*******************************************************/ -static void lockit(void) -{ - if (shared_fd == 0) { - char *p = getenv("SMBW_HANDLE"); - if (!p) { - DEBUG(0,("ERROR: can't get smbw shared handle\n")); - exit(1); - } - shared_fd = atoi(p); - } - if (locked==0 && - fcntl_lock(shared_fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) { - DEBUG(0,("ERROR: can't get smbw shared lock (%s)\n", strerror(errno))); - exit(1); - } - locked++; -} - -/***************************************************** -unlock the shared variable area -*******************************************************/ -static void unlockit(void) -{ - locked--; - if (locked == 0) { - fcntl_lock(shared_fd,SMB_F_SETLK,0,1,F_UNLCK); - } -} - - -/***************************************************** -get a variable from the shared area -*******************************************************/ -char *smbw_getshared(const char *name) -{ - int i; - struct stat st; - char *var; - - lockit(); - - /* maybe the area has changed */ - if (fstat(shared_fd, &st)) goto failed; - - if (st.st_size != shared_size) { - var = (char *)Realloc(variables, st.st_size); - if (!var) goto failed; - else variables = var; - shared_size = st.st_size; - lseek(shared_fd, 0, SEEK_SET); - if (read(shared_fd, variables, shared_size) != shared_size) { - goto failed; - } - } - - unlockit(); - - i=0; - while (i < shared_size) { - char *n, *v; - int l1, l2; - - l1 = SVAL(&variables[i], 0); - l2 = SVAL(&variables[i], 2); - - n = &variables[i+4]; - v = &variables[i+4+l1]; - i += 4+l1+l2; - - if (strcmp(name,n)) { - continue; - } - return v; - } - - return NULL; - - failed: - DEBUG(0,("smbw: shared variables corrupt (%s)\n", strerror(errno))); - exit(1); - return NULL; -} - - - -/***************************************************** -set a variable in the shared area -*******************************************************/ -void smbw_setshared(const char *name, const char *val) -{ - int l1, l2; - char *var; - - /* we don't allow variable overwrite */ - if (smbw_getshared(name)) return; - - lockit(); - - l1 = strlen(name)+1; - l2 = strlen(val)+1; - - var = (char *)Realloc(variables, shared_size + l1+l2+4); - - if (!var) { - DEBUG(0,("out of memory in smbw_setshared\n")); - exit(1); - } - - variables = var; - - SSVAL(&variables[shared_size], 0, l1); - SSVAL(&variables[shared_size], 2, l2); - - pstrcpy(&variables[shared_size] + 4, name); - pstrcpy(&variables[shared_size] + 4 + l1, val); - - shared_size += l1+l2+4; - - lseek(shared_fd, 0, SEEK_SET); - if (write(shared_fd, variables, shared_size) != shared_size) { - DEBUG(0,("smbw_setshared failed (%s)\n", strerror(errno))); - exit(1); - } - - unlockit(); -} - - -/***************************************************************** -return true if the passed fd is the SMBW_HANDLE -*****************************************************************/ -int smbw_shared_fd(int fd) -{ - return (shared_fd && shared_fd == fd); -} diff --git a/source4/smbwrapper/smbsh.c b/source4/smbwrapper/smbsh.c deleted file mode 100644 index 221c6d87c2..0000000000 --- a/source4/smbwrapper/smbsh.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - frontend - Copyright (C) Andrew Tridgell 1998 - - 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" - -static void smbsh_usage(void) -{ - printf("smbsh [options]\n\n"); - printf(" -W workgroup\n"); - printf(" -U username\n"); - printf(" -P prefix\n"); - printf(" -R resolve order\n"); - printf(" -d debug level\n"); - printf(" -l logfile\n"); - printf(" -L libdir\n"); - exit(0); -} - -int main(int argc, char *argv[]) -{ - char *p, *u; - const char *libd = dyn_BINDIR; - pstring line, wd; - int opt; - extern char *optarg; - extern int optind; - - dbf = x_stdout; - smbw_setup_shared(); - - while ((opt = getopt(argc, argv, "W:U:R:d:P:l:hL:")) != EOF) { - switch (opt) { - case 'L': - libd = optarg; - break; - case 'W': - smbw_setshared("WORKGROUP", optarg); - break; - case 'l': - smbw_setshared("LOGFILE", optarg); - break; - case 'P': - smbw_setshared("PREFIX", optarg); - break; - case 'd': - smbw_setshared("DEBUG", optarg); - break; - case 'U': - p = strchr_m(optarg,'%'); - if (p) { - *p=0; - smbw_setshared("PASSWORD",p+1); - } - smbw_setshared("USER", optarg); - break; - case 'R': - smbw_setshared("RESOLVE_ORDER",optarg); - break; - - case 'h': - default: - smbsh_usage(); - } - } - - - if (!smbw_getshared("USER")) { - printf("Username: "); - u = fgets_slash(line, sizeof(line)-1, x_stdin); - smbw_setshared("USER", u); - } - - if (!smbw_getshared("PASSWORD")) { - p = getpass("Password: "); - smbw_setshared("PASSWORD", p); - } - - setenv("PS1", "smbsh$ ", 1); - - sys_getwd(wd); - - slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); - - smbw_setshared(line, wd); - - slprintf(line,sizeof(line)-1,"%s/smbwrapper.so", libd); - setenv("LD_PRELOAD", line, 1); - - slprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so", libd); - - if (file_exist(line, NULL)) { - slprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so:DEFAULT", libd); - setenv("_RLD_LIST", line, 1); - slprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd); - setenv("_RLDN32_LIST", line, 1); - } else { - slprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd); - setenv("_RLD_LIST", line, 1); - } - - { - char *shellpath = getenv("SHELL"); - if(shellpath) - execl(shellpath,"smbsh",NULL); - else - execl("/bin/sh","smbsh",NULL); - } - printf("launch failed!\n"); - return 1; -} diff --git a/source4/smbwrapper/smbsh.in b/source4/smbwrapper/smbsh.in deleted file mode 100644 index 323f091699..0000000000 --- a/source4/smbwrapper/smbsh.in +++ /dev/null @@ -1,54 +0,0 @@ -#! /bin/sh - -SMBW_LIBDIR=${SMBW_LIBDIR-@builddir@/smbwrapper} - -if [ ! -f ${SMBW_LIBDIR}/smbwrapper.so ]; then - echo You need to set LIBDIR in smbsh - exit -fi - -# a simple launcher for the smbwrapper.so preloadde library - -if [ x"${SMBW_USER+set}" != x"set" ]; then - echo username? - read user - SMBW_USER=$user - export SMBW_USER -fi - -# this doesn't hide the password - we need a proper launch app for that -if [ x"${SMBW_PASSWORD+set}" != x"set" ]; then - echo password? - read pass - SMBW_PASSWORD=$pass - export SMBW_PASSWORD -fi - -PWD=`pwd` -export PWD -PS1='smbsh$ ' -export PS1 - - -host_os=@HOST_OS@ - -case "$host_os" in - *irix*) - _RLDN32_LIST=$SMBW_LIBDIR/smbwrapper.so:DEFAULT - _RLD_LIST=$SMBW_LIBDIR/smbwrapper.32.so:DEFAULT - export _RLDN32_LIST - export _RLD_LIST - ;; - *osf*) - _RLD_LIST=$SMBW_LIBDIR/smbwrapper.so:DEFAULT - export _RLD_LIST - ;; - *) - LD_PRELOAD=$SMBW_LIBDIR/smbwrapper.so - export LD_PRELOAD - ;; -esac - -echo starting smbwrapper on $host_os - -exec ${SMBW_SHELL-${SHELL-/bin/sh}} ${1+"$@"} diff --git a/source4/smbwrapper/smbw.c b/source4/smbwrapper/smbw.c deleted file mode 100644 index c62533dc2a..0000000000 --- a/source4/smbwrapper/smbw.c +++ /dev/null @@ -1,1554 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - Copyright (C) Andrew Tridgell 1998 - - 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 "realcalls.h" - -pstring smbw_cwd; - -static struct smbw_file *smbw_files; -static struct smbw_server *smbw_srvs; - -struct bitmap *smbw_file_bmap; - -fstring smbw_prefix = SMBW_PREFIX; - -int smbw_busy=0; - -/* needs to be here because of dumb include files on some systems */ -int creat_bits = O_WRONLY|O_CREAT|O_TRUNC; - - -/***************************************************** -initialise structures -*******************************************************/ -void smbw_init(void) -{ - extern BOOL in_client; - static int initialised; - char *p; - int eno; - pstring line; - - if (initialised) return; - initialised = 1; - - eno = errno; - - smbw_busy++; - - DEBUGLEVEL = 0; - setup_logging("smbsh", DEBUG_STDOUT); - - dbf = x_stderr; - - if ((p=smbw_getshared("LOGFILE"))) { - dbf = sys_fopen(p, "a"); - } - - smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN); - if (!smbw_file_bmap) { - exit(1); - } - - in_client = True; - - load_interfaces(); - - if ((p=smbw_getshared("SERVICESF"))) { - pstrcpy(dyn_CONFIGFILE, p); - } - - lp_load(dyn_CONFIGFILE,True,False,False); - - if (!init_names()) - exit(1); - - if ((p=smbw_getshared("DEBUG"))) { - DEBUGLEVEL = atoi(p); - } - - if ((p=smbw_getshared("RESOLVE_ORDER"))) { - lp_set_name_resolve_order(p); - } - - if ((p=smbw_getshared("PREFIX"))) { - slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p); - all_string_sub(smbw_prefix,"//", "/", 0); - DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix)); - } - - slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); - - p = smbw_getshared(line); - if (!p) { - sys_getwd(smbw_cwd); - } - pstrcpy(smbw_cwd, p); - DEBUG(4,("Initial cwd is %s\n", smbw_cwd)); - - smbw_busy--; - - set_maxfiles(SMBW_MAX_OPEN); - - BlockSignals(True,SIGPIPE); - - errno = eno; -} - -/***************************************************** -determine if a file descriptor is a smb one -*******************************************************/ -int smbw_fd(int fd) -{ - if (smbw_busy) return 0; - return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd); -} - -/***************************************************** -determine if a file descriptor is an internal smbw fd -*******************************************************/ -int smbw_local_fd(int fd) -{ - struct smbw_server *srv; - - smbw_init(); - - if (smbw_busy) return 0; - if (smbw_shared_fd(fd)) return 1; - - for (srv=smbw_srvs;srv;srv=srv->next) { - if (srv->cli.fd == fd) return 1; - } - - return 0; -} - -/***************************************************** -a crude inode number generator -*******************************************************/ -ino_t smbw_inode(const char *name) -{ - if (!*name) return 2; - return (ino_t)str_checksum(name); -} - -/***************************************************** -remove redundent stuff from a filename -*******************************************************/ -void clean_fname(char *name) -{ - char *p, *p2; - int l; - int modified = 1; - - if (!name) return; - - while (modified) { - modified = 0; - - DEBUG(5,("cleaning %s\n", name)); - - if ((p=strstr(name,"/./"))) { - modified = 1; - while (*p) { - p[0] = p[2]; - p++; - } - } - - if ((p=strstr(name,"//"))) { - modified = 1; - while (*p) { - p[0] = p[1]; - p++; - } - } - - if (strcmp(name,"/../")==0) { - modified = 1; - name[1] = 0; - } - - if ((p=strstr(name,"/../"))) { - modified = 1; - for (p2=(p>name?p-1:p);p2>name;p2--) { - if (p2[0] == '/') break; - } - while (*p2) { - p2[0] = p2[3]; - p2++; - } - } - - if (strcmp(name,"/..")==0) { - modified = 1; - name[1] = 0; - } - - l = strlen(name); - p = l>=3?(name+l-3):name; - if (strcmp(p,"/..")==0) { - modified = 1; - for (p2=p-1;p2>name;p2--) { - if (p2[0] == '/') break; - } - if (p2==name) { - p[0] = '/'; - p[1] = 0; - } else { - p2[0] = 0; - } - } - - l = strlen(name); - p = l>=2?(name+l-2):name; - if (strcmp(p,"/.")==0) { - if (p == name) { - p[1] = 0; - } else { - p[0] = 0; - } - } - - if (strncmp(p=name,"./",2) == 0) { - modified = 1; - do { - p[0] = p[2]; - } while (*p++); - } - - l = strlen(p=name); - if (l > 1 && p[l-1] == '/') { - modified = 1; - p[l-1] = 0; - } - } -} - - - -/***************************************************** -find a workgroup (any workgroup!) that has a master -browser on the local network -*******************************************************/ -static char *smbw_find_workgroup(void) -{ - fstring server; - char *p; - struct in_addr *ip_list = NULL; - int count = 0; - int i; - - /* first off see if an existing workgroup name exists */ - p = smbw_getshared("WORKGROUP"); - if (!p) p = lp_workgroup(); - - slprintf(server, sizeof(server), "%s#1D", p); - if (smbw_server(server, "IPC$")) return p; - - /* go looking for workgroups */ - if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) { - DEBUG(1,("No workgroups found!")); - return p; - } - - for (i=0;i<count;i++) { - static fstring name; - if (name_status_find("*", 0, 0x1d, ip_list[i], name)) { - slprintf(server, sizeof(server), "%s#1D", name); - if (smbw_server(server, "IPC$")) { - smbw_setshared("WORKGROUP", name); - SAFE_FREE(ip_list); - return name; - } - } - } - - SAFE_FREE(ip_list); - - return p; -} - -/***************************************************** -parse a smb path into its components. -server is one of - 1) the name of the SMB server - 2) WORKGROUP#1D for share listing - 3) WORKGROUP#__ for workgroup listing -share is the share on the server to query -path is the SMB path on the server -return the full path (ie. add cwd if needed) -*******************************************************/ -char *smbw_parse_path(const char *fname, char *server, char *share, char *path) -{ - static pstring s; - char *p; - int len; - fstring workgroup; - - /* add cwd if necessary */ - if (fname[0] != '/') { - slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname); - } else { - pstrcpy(s, fname); - } - clean_fname(s); - - /* see if it has the right prefix */ - len = strlen(smbw_prefix)-1; - if (strncmp(s,smbw_prefix,len) || - (s[len] != '/' && s[len] != 0)) return s; - - /* ok, its for us. Now parse out the workgroup, share etc. */ - p = s+len; - if (*p == '/') p++; - if (!next_token(&p, workgroup, "/", sizeof(fstring))) { - /* we're in /smb - give a list of workgroups */ - slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup()); - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - return s; - } - - if (!next_token(&p, server, "/", sizeof(fstring))) { - /* we are in /smb/WORKGROUP */ - slprintf(server,sizeof(fstring), "%s#1D", workgroup); - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - } - - if (!next_token(&p, share, "/", sizeof(fstring))) { - /* we are in /smb/WORKGROUP/SERVER */ - fstrcpy(share,"IPC$"); - pstrcpy(path,""); - } - - pstrcpy(path, p); - - all_string_sub(path, "/", "\\", 0); - - return s; -} - -/***************************************************** -determine if a path name (possibly relative) is in the -smb name space -*******************************************************/ -int smbw_path(const char *path) -{ - fstring server, share; - pstring s; - char *cwd; - int len; - - if(!path) - return 0; - - /* this is needed to prevent recursion with the BSD malloc which - opens /etc/malloc.conf on the first call */ - if (strncmp(path,"/etc/", 5) == 0) { - return 0; - } - - smbw_init(); - - len = strlen(smbw_prefix)-1; - - if (path[0] == '/' && strncmp(path,smbw_prefix,len)) { - return 0; - } - - if (smbw_busy) return 0; - - DEBUG(3,("smbw_path(%s)\n", path)); - - cwd = smbw_parse_path(path, server, share, s); - - if (strncmp(cwd,smbw_prefix,len) == 0 && - (cwd[len] == '/' || cwd[len] == 0)) { - return 1; - } - - return 0; -} - -/***************************************************** -return a unix errno from a SMB error pair -*******************************************************/ -int smbw_errno(struct cli_state *c) -{ - return cli_errno(c); -} - -/* Return a username and password given a server and share name */ - -void get_envvar_auth_data(char *server, char *share, char **workgroup, - char **username, char **password) -{ - /* Fall back to shared memory/environment variables */ - - *username = smbw_getshared("USER"); - if (!*username) *username = getenv("USER"); - if (!*username) *username = "guest"; - - *workgroup = smbw_getshared("WORKGROUP"); - if (!*workgroup) *workgroup = lp_workgroup(); - - *password = smbw_getshared("PASSWORD"); - if (!*password) *password = ""; -} - -static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data; - -/***************************************************** -set the get auth data function -******************************************************/ -void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn) -{ - get_auth_data_fn = fn; -} - -/***************************************************** -return a connection to a server (existing or new) -*******************************************************/ -struct smbw_server *smbw_server(char *server, char *share) -{ - struct smbw_server *srv=NULL; - struct cli_state c; - char *username; - char *password; - char *workgroup; - struct nmb_name called, calling; - char *p, *server_n = server; - fstring group; - pstring ipenv; - struct in_addr ip; - - zero_ip(&ip); - ZERO_STRUCT(c); - - get_auth_data_fn(server, share, &workgroup, &username, &password); - - /* try to use an existing connection */ - for (srv=smbw_srvs;srv;srv=srv->next) { - if (strcmp(server,srv->server_name)==0 && - strcmp(share,srv->share_name)==0 && - strcmp(workgroup,srv->workgroup)==0 && - strcmp(username, srv->username) == 0) - return srv; - } - - if (server[0] == 0) { - errno = EPERM; - return NULL; - } - - make_nmb_name(&calling, lp_netbios_name(), 0x0); - make_nmb_name(&called , server, 0x20); - - DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server)); - - if ((p=strchr_m(server_n,'#')) && - (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) { - struct in_addr sip; - pstring s; - - fstrcpy(group, server_n); - p = strchr_m(group,'#'); - *p = 0; - - /* cache the workgroup master lookup */ - slprintf(s,sizeof(s)-1,"MASTER_%s", group); - if (!(server_n = smbw_getshared(s))) { - if (!find_master_ip(group, &sip)) { - errno = ENOENT; - return NULL; - } - fstrcpy(group, inet_ntoa(sip)); - server_n = group; - smbw_setshared(s,server_n); - } - } - - DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); - - again: - slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n); - - zero_ip(&ip); - if ((p=smbw_getshared(ipenv))) { - ip = *(interpret_addr2(p)); - } - - /* have to open a new connection */ - if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) { - errno = ENOENT; - return NULL; - } - - if (!cli_session_request(&c, &calling, &called)) { - cli_shutdown(&c); - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - errno = ENOENT; - return NULL; - } - - DEBUG(4,(" session request ok\n")); - - if (!cli_negprot(&c)) { - cli_shutdown(&c); - errno = ENOENT; - return NULL; - } - - if (!cli_session_setup(&c, username, - password, strlen(password), - password, strlen(password), - workgroup) && - /* try an anonymous login if it failed */ - !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) { - cli_shutdown(&c); - errno = EPERM; - return NULL; - } - - DEBUG(4,(" session setup ok\n")); - - if (!cli_send_tconX(&c, share, "?????", - password, strlen(password)+1)) { - errno = smbw_errno(&c); - cli_shutdown(&c); - return NULL; - } - - smbw_setshared(ipenv,inet_ntoa(ip)); - - DEBUG(4,(" tconx ok\n")); - - srv = (struct smbw_server *)malloc(sizeof(*srv)); - if (!srv) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(srv); - - srv->cli = c; - - srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); - - srv->server_name = strdup(server); - if (!srv->server_name) { - errno = ENOMEM; - goto failed; - } - - srv->share_name = strdup(share); - if (!srv->share_name) { - errno = ENOMEM; - goto failed; - } - - srv->workgroup = strdup(workgroup); - if (!srv->workgroup) { - errno = ENOMEM; - goto failed; - } - - srv->username = strdup(username); - if (!srv->username) { - errno = ENOMEM; - goto failed; - } - - /* some programs play with file descriptors fairly intimately. We - try to get out of the way by duping to a high fd number */ - if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) { - if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == - srv->cli.fd+SMBW_CLI_FD) { - close(srv->cli.fd); - srv->cli.fd += SMBW_CLI_FD; - } - } - - DLIST_ADD(smbw_srvs, srv); - - return srv; - - failed: - cli_shutdown(&c); - if (!srv) return NULL; - - SAFE_FREE(srv->server_name); - SAFE_FREE(srv->share_name); - SAFE_FREE(srv); - return NULL; -} - - -/***************************************************** -map a fd to a smbw_file structure -*******************************************************/ -struct smbw_file *smbw_file(int fd) -{ - struct smbw_file *file; - - for (file=smbw_files;file;file=file->next) { - if (file->fd == fd) return file; - } - return NULL; -} - -/***************************************************** -a wrapper for open() -*******************************************************/ -int smbw_open(const char *fname, int flags, mode_t mode) -{ - fstring server, share; - pstring path; - struct smbw_server *srv=NULL; - int eno=0, fd = -1; - struct smbw_file *file=NULL; - - smbw_init(); - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (path[strlen(path)-1] == '\\') { - fd = -1; - } else { - fd = cli_open(&srv->cli, path, flags, DENY_NONE); - } - if (fd == -1) { - /* it might be a directory. Maybe we should use chkpath? */ - eno = smbw_errno(&srv->cli); - fd = smbw_dir_open(fname); - if (fd == -1) errno = eno; - smbw_busy--; - return fd; - } - - file = (struct smbw_file *)malloc(sizeof(*file)); - if (!file) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file); - - file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f))); - if (!file->f) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file->f); - - file->f->cli_fd = fd; - file->f->fname = strdup(path); - if (!file->f->fname) { - errno = ENOMEM; - goto failed; - } - file->srv = srv; - file->fd = open(SMBW_DUMMY, O_WRONLY); - if (file->fd == -1) { - errno = EMFILE; - goto failed; - } - - if (bitmap_query(smbw_file_bmap, file->fd)) { - DEBUG(0,("ERROR: fd used in smbw_open\n")); - errno = EIO; - goto failed; - } - - file->f->ref_count=1; - - bitmap_set(smbw_file_bmap, file->fd); - - DLIST_ADD(smbw_files, file); - - DEBUG(4,("opened %s\n", fname)); - - smbw_busy--; - return file->fd; - - failed: - if (fd != -1) { - cli_close(&srv->cli, fd); - } - if (file) { - if (file->f) { - SAFE_FREE(file->f->fname); - SAFE_FREE(file->f); - } - SAFE_FREE(file); - } - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for pread() -*******************************************************/ -ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for read() -*******************************************************/ -ssize_t smbw_read(int fd, void *buf, size_t count) -{ - struct smbw_file *file; - int ret; - - DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count)); - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, - file->f->offset, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - file->f->offset += ret; - - DEBUG(4,(" -> %d\n", ret)); - - smbw_busy--; - return ret; -} - - - -/***************************************************** -a wrapper for write() -*******************************************************/ -ssize_t smbw_write(int fd, void *buf, size_t count) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - file->f->offset += ret; - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for pwrite() -*******************************************************/ -ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs) -{ - struct smbw_file *file; - int ret; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - smbw_busy--; - return -1; - } - - ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count); - - if (ret == -1) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - smbw_busy--; - return ret; -} - -/***************************************************** -a wrapper for close() -*******************************************************/ -int smbw_close(int fd) -{ - struct smbw_file *file; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - int ret = smbw_dir_close(fd); - smbw_busy--; - return ret; - } - - if (file->f->ref_count == 1 && - !cli_close(&file->srv->cli, file->f->cli_fd)) { - errno = smbw_errno(&file->srv->cli); - smbw_busy--; - return -1; - } - - - bitmap_clear(smbw_file_bmap, file->fd); - close(file->fd); - - DLIST_REMOVE(smbw_files, file); - - file->f->ref_count--; - if (file->f->ref_count == 0) { - SAFE_FREE(file->f->fname); - SAFE_FREE(file->f); - } - ZERO_STRUCTP(file); - SAFE_FREE(file); - - smbw_busy--; - - return 0; -} - - -/***************************************************** -a wrapper for fcntl() -*******************************************************/ -int smbw_fcntl(int fd, int cmd, long arg) -{ - return 0; -} - - -/***************************************************** -a wrapper for access() -*******************************************************/ -int smbw_access(const char *name, int mode) -{ - struct stat st; - - DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode)); - - if (smbw_stat(name, &st)) return -1; - - if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) || - ((mode & W_OK) && !(st.st_mode & S_IWUSR)) || - ((mode & X_OK) && !(st.st_mode & S_IXUSR))) { - errno = EACCES; - return -1; - } - - return 0; -} - -/***************************************************** -a wrapper for realink() - needed for correct errno setting -*******************************************************/ -int smbw_readlink(const char *path, char *buf, size_t bufsize) -{ - struct stat st; - int ret; - - ret = smbw_stat(path, &st); - if (ret != 0) { - DEBUG(4,("readlink(%s) failed\n", path)); - return -1; - } - - /* it exists - say it isn't a link */ - DEBUG(4,("readlink(%s) not a link\n", path)); - - errno = EINVAL; - return -1; -} - - -/***************************************************** -a wrapper for unlink() -*******************************************************/ -int smbw_unlink(const char *fname) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (strncmp(srv->cli.dev, "LPT", 3) == 0) { - int job = smbw_stat_printjob(srv, path, NULL, NULL); - if (job == -1) { - goto failed; - } - if (cli_printjob_del(&srv->cli, job) != 0) { - goto failed; - } - } else if (!cli_unlink(&srv->cli, path)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for rename() -*******************************************************/ -int smbw_rename(const char *oldname, const char *newname) -{ - struct smbw_server *srv; - fstring server1, share1; - pstring path1; - fstring server2, share2; - pstring path2; - - if (!oldname || !newname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname)); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(oldname, server1, share1, path1); - smbw_parse_path(newname, server2, share2, path2); - - if (strcmp(server1, server2) || strcmp(share1, share2)) { - /* can't cross filesystems */ - errno = EXDEV; - return -1; - } - - /* get a connection to the server */ - srv = smbw_server(server1, share1); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_rename(&srv->cli, path1, path2)) { - int eno = smbw_errno(&srv->cli); - if (eno != EEXIST || - !cli_unlink(&srv->cli, path2) || - !cli_rename(&srv->cli, path1, path2)) { - errno = eno; - goto failed; - } - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for utime and utimes -*******************************************************/ -static int smbw_settime(const char *fname, time_t t) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint16 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - if (!cli_setatr(&srv->cli, path, mode, t)) { - /* some servers always refuse directory changes */ - if (!(mode & aDIR)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for utime -*******************************************************/ -int smbw_utime(const char *fname, void *buf) -{ - struct utimbuf *tbuf = (struct utimbuf *)buf; - return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL)); -} - -/***************************************************** -a wrapper for utime -*******************************************************/ -int smbw_utimes(const char *fname, void *buf) -{ - struct timeval *tbuf = (struct timeval *)buf; - return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL)); -} - - -/***************************************************** -a wrapper for chown() -*******************************************************/ -int smbw_chown(const char *fname, uid_t owner, gid_t group) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint16 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - /* assume success */ - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for chmod() -*******************************************************/ -int smbw_chmod(const char *fname, mode_t newmode) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint32 mode; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - mode = 0; - - if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; - if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; - if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; - if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - - if (!cli_setatr(&srv->cli, path, mode, 0)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for lseek() -*******************************************************/ -off_t smbw_lseek(int fd, off_t offset, int whence) -{ - struct smbw_file *file; - size_t size; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - off_t ret = smbw_dir_lseek(fd, offset, whence); - smbw_busy--; - return ret; - } - - switch (whence) { - case SEEK_SET: - file->f->offset = offset; - break; - case SEEK_CUR: - file->f->offset += offset; - break; - case SEEK_END: - if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, - NULL, &size, NULL, NULL, NULL, - NULL, NULL) && - !cli_getattrE(&file->srv->cli, file->f->cli_fd, - NULL, &size, NULL, NULL, NULL)) { - errno = EINVAL; - smbw_busy--; - return -1; - } - file->f->offset = size + offset; - break; - } - - smbw_busy--; - return file->f->offset; -} - - -/***************************************************** -a wrapper for dup() -*******************************************************/ -int smbw_dup(int fd) -{ - int fd2; - struct smbw_file *file, *file2; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - goto failed; - } - - fd2 = dup(file->fd); - if (fd2 == -1) { - goto failed; - } - - if (bitmap_query(smbw_file_bmap, fd2)) { - DEBUG(0,("ERROR: fd already open in dup!\n")); - errno = EIO; - goto failed; - } - - file2 = (struct smbw_file *)malloc(sizeof(*file2)); - if (!file2) { - close(fd2); - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file2); - - *file2 = *file; - file2->fd = fd2; - - file->f->ref_count++; - - bitmap_set(smbw_file_bmap, fd2); - - DLIST_ADD(smbw_files, file2); - - smbw_busy--; - return fd2; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for dup2() -*******************************************************/ -int smbw_dup2(int fd, int fd2) -{ - struct smbw_file *file, *file2; - - smbw_busy++; - - file = smbw_file(fd); - if (!file) { - errno = EBADF; - goto failed; - } - - if (bitmap_query(smbw_file_bmap, fd2)) { - DEBUG(0,("ERROR: fd already open in dup2!\n")); - errno = EIO; - goto failed; - } - - if (dup2(file->fd, fd2) != fd2) { - goto failed; - } - - file2 = (struct smbw_file *)malloc(sizeof(*file2)); - if (!file2) { - close(fd2); - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(file2); - - *file2 = *file; - file2->fd = fd2; - - file->f->ref_count++; - - bitmap_set(smbw_file_bmap, fd2); - - DLIST_ADD(smbw_files, file2); - - smbw_busy--; - return fd2; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -close a connection to a server -*******************************************************/ -static void smbw_srv_close(struct smbw_server *srv) -{ - smbw_busy++; - - cli_shutdown(&srv->cli); - - SAFE_FREE(srv->server_name); - SAFE_FREE(srv->share_name); - - DLIST_REMOVE(smbw_srvs, srv); - - ZERO_STRUCTP(srv); - - SAFE_FREE(srv); - - smbw_busy--; -} - -/***************************************************** -when we fork we have to close all connections and files -in the child -*******************************************************/ -int smbw_fork(void) -{ - pid_t child; - int p[2]; - char c=0; - pstring line; - - struct smbw_file *file, *next_file; - struct smbw_server *srv, *next_srv; - - if (pipe(p)) return real_fork(); - - child = real_fork(); - - if (child) { - /* block the parent for a moment until the sockets are - closed */ - close(p[1]); - read(p[0], &c, 1); - close(p[0]); - return child; - } - - close(p[0]); - - /* close all files */ - for (file=smbw_files;file;file=next_file) { - next_file = file->next; - close(file->fd); - } - - /* close all server connections */ - for (srv=smbw_srvs;srv;srv=next_srv) { - next_srv = srv->next; - smbw_srv_close(srv); - } - - slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); - smbw_setshared(line,smbw_cwd); - - /* unblock the parent */ - write(p[1], &c, 1); - close(p[1]); - - /* and continue in the child */ - return 0; -} - -#ifndef NO_ACL_WRAPPER -/***************************************************** -say no to acls -*******************************************************/ - int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp) -{ - if (cmd == GETACL || cmd == GETACLCNT) return 0; - errno = ENOSYS; - return -1; -} -#endif - -#ifndef NO_FACL_WRAPPER -/***************************************************** -say no to acls -*******************************************************/ - int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp) -{ - if (cmd == GETACL || cmd == GETACLCNT) return 0; - errno = ENOSYS; - return -1; -} -#endif - -#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT -#ifdef HAVE_STAT64 -/* this can't be in wrapped.c because of include conflicts */ - void stat64_convert(struct stat *st, struct stat64 *st64) -{ - st64->st_size = st->st_size; - st64->st_mode = st->st_mode; - st64->st_ino = st->st_ino; - st64->st_dev = st->st_dev; - st64->st_rdev = st->st_rdev; - st64->st_nlink = st->st_nlink; - st64->st_uid = st->st_uid; - st64->st_gid = st->st_gid; - st64->st_atime = st->st_atime; - st64->st_mtime = st->st_mtime; - st64->st_ctime = st->st_ctime; - st64->st_blksize = st->st_blksize; - st64->st_blocks = st->st_blocks; -} -#endif - -#ifdef HAVE_READDIR64 - void dirent64_convert(struct dirent *d, struct dirent64 *d64) -{ - d64->d_ino = d->d_ino; - d64->d_off = d->d_off; - d64->d_reclen = d->d_reclen; - pstrcpy(d64->d_name, d->d_name); -} -#endif -#endif - - -#ifdef HAVE___XSTAT -/* Definition of `struct stat' used in the linux kernel.. */ -struct kernel_stat { - unsigned short int st_dev; - unsigned short int __pad1; - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - unsigned long int st_atime; - unsigned long int __unused1; - unsigned long int st_mtime; - unsigned long int __unused2; - unsigned long int st_ctime; - unsigned long int __unused3; - unsigned long int __unused4; - unsigned long int __unused5; -}; - -/* - * Prototype for gcc in 'fussy' mode. - */ - void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf); - void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf) -{ -#ifdef _STAT_VER_LINUX_OLD - if (vers == _STAT_VER_LINUX_OLD) { - memcpy(st, kbuf, sizeof(*st)); - return; - } -#endif - - ZERO_STRUCTP(st); - - st->st_dev = kbuf->st_dev; - st->st_ino = kbuf->st_ino; - st->st_mode = kbuf->st_mode; - st->st_nlink = kbuf->st_nlink; - st->st_uid = kbuf->st_uid; - st->st_gid = kbuf->st_gid; - st->st_rdev = kbuf->st_rdev; - st->st_size = kbuf->st_size; - st->st_blksize = kbuf->st_blksize; - st->st_blocks = kbuf->st_blocks; - st->st_atime = kbuf->st_atime; - st->st_mtime = kbuf->st_mtime; - st->st_ctime = kbuf->st_ctime; -} -#endif diff --git a/source4/smbwrapper/smbw.h b/source4/smbwrapper/smbw.h deleted file mode 100644 index 3f0b1cbb44..0000000000 --- a/source4/smbwrapper/smbw.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - definitions - Copyright (C) Andrew Tridgell 1998 - - 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 _SMBW_H -#define _SMBW_H - -#define SMBW_PREFIX "/smb/" -#define SMBW_DUMMY "/dev/null" - -#define SMBW_CLI_FD 512 -#define SMBW_MAX_OPEN 8192 - -#define SMBW_FILE_MODE (S_IFREG | 0444) -#define SMBW_DIR_MODE (S_IFDIR | 0555) - -struct smbw_server { - struct smbw_server *next, *prev; - struct cli_state cli; - char *server_name; - char *share_name; - char *workgroup; - char *username; - dev_t dev; - BOOL no_pathinfo2; -}; - -struct smbw_filedes { - int cli_fd; - int ref_count; - char *fname; - off_t offset; -}; - -struct smbw_file { - struct smbw_file *next, *prev; - struct smbw_filedes *f; - int fd; - struct smbw_server *srv; -}; - -struct smbw_dir { - struct smbw_dir *next, *prev; - int fd; - int offset, count, malloced; - struct smbw_server *srv; - struct file_info *list; - char *path; -}; - -typedef void (*smbw_get_auth_data_fn)(char *server, char *share, - char **workgroup, char **username, - char **password); - -#endif /* _SMBW_H */ diff --git a/source4/smbwrapper/smbw_cache.c b/source4/smbwrapper/smbw_cache.c deleted file mode 100644 index fcb0eda805..0000000000 --- a/source4/smbwrapper/smbw_cache.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper directory functions - Copyright (C) Tim Potter 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" - -/* We cache lists of workgroups, lists of servers in workgroups, and lists - of shares exported by servers. */ - -#define CACHE_TIMEOUT 30 - -struct name_list { - struct name_list *prev, *next; - char *name; - uint32 stype; - char *comment; -}; - -struct cached_names { - struct cached_names *prev, *next; - char *key; - struct name_list *name_list; - time_t cache_timeout; - int result; -}; - -static struct cached_names *cached_names = NULL; - -/* Find a list of cached name for a workgroup, server or share list */ - -static struct cached_names *find_cached_names(char *key) -{ - struct cached_names *tmp; - - for (tmp = cached_names; tmp; tmp = tmp->next) { - if (strequal(tmp->key, key)) { - return tmp; - } - } - - return NULL; -} - -/* Add a name to a list stored in the state variable */ - -static void add_cached_names(const char *name, uint32 stype, - const char *comment, void *state) -{ - struct name_list **name_list = (struct name_list **)state; - struct name_list *new_name; - - new_name = (struct name_list *)malloc(sizeof(struct name_list)); - if (!new_name) return; - - ZERO_STRUCTP(new_name); - - new_name->name = strdup(name); - new_name->stype = stype; - new_name->comment = strdup(comment); - - DLIST_ADD(*name_list, new_name); -} - -static void free_name_list(struct name_list *name_list) -{ - struct name_list *tmp = name_list; - - while(tmp) { - struct name_list *next; - - next = tmp->next; - - SAFE_FREE(tmp->name); - SAFE_FREE(tmp->comment); - SAFE_FREE(tmp); - - tmp = next; - } -} - -/* Wrapper for NetServerEnum function */ - -BOOL smbw_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, - void (*fn)(const char *, uint32, const char *, void *), - void *state) -{ - struct cached_names *names; - struct name_list *tmp; - time_t now = time(NULL); - char key[PATH_MAX]; - BOOL result = True; - - slprintf(key, PATH_MAX - 1, "%s/%s#%s", cli->desthost, - workgroup, (stype == SV_TYPE_DOMAIN_ENUM ? "DOM" : "SRV")); - - names = find_cached_names(key); - - if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) { - struct cached_names *new_names = NULL; - - /* No names cached for this workgroup */ - - if (names == NULL) { - new_names = (struct cached_names *) - malloc(sizeof(struct cached_names)); - - ZERO_STRUCTP(new_names); - DLIST_ADD(cached_names, new_names); - - } else { - - /* Dispose of out of date name list */ - - free_name_list(names->name_list); - names->name_list = NULL; - - new_names = names; - } - - result = cli_NetServerEnum(cli, workgroup, stype, - add_cached_names, - &new_names->name_list); - - new_names->cache_timeout = now; - new_names->result = result; - new_names->key = strdup(key); - - names = new_names; - } - - /* Return names by running callback function. */ - - for (tmp = names->name_list; tmp; tmp = tmp->next) - fn(tmp->name, stype, tmp->comment, state); - - return names->result; -} - -/* Wrapper for RNetShareEnum function */ - -int smbw_RNetShareEnum(struct cli_state *cli, - void (*fn)(const char *, uint32, const char *, void *), - void *state) -{ - struct cached_names *names; - struct name_list *tmp; - time_t now = time(NULL); - char key[PATH_MAX]; - - slprintf(key, PATH_MAX - 1, "SHARE/%s", cli->desthost); - - names = find_cached_names(key); - - if (names == NULL || (now - names->cache_timeout) > CACHE_TIMEOUT) { - struct cached_names *new_names = NULL; - - /* No names cached for this server */ - - if (names == NULL) { - new_names = (struct cached_names *) - malloc(sizeof(struct cached_names)); - - ZERO_STRUCTP(new_names); - DLIST_ADD(cached_names, new_names); - - } else { - - /* Dispose of out of date name list */ - - free_name_list(names->name_list); - names->name_list = NULL; - - new_names = names; - } - - new_names->result = cli_RNetShareEnum(cli, add_cached_names, - &new_names->name_list); - - new_names->cache_timeout = now; - new_names->key = strdup(key); - - names = new_names; - } - - /* Return names by running callback function. */ - - for (tmp = names->name_list; tmp; tmp = tmp->next) - fn(tmp->name, tmp->stype, tmp->comment, state); - - return names->result; -} diff --git a/source4/smbwrapper/smbw_dir.c b/source4/smbwrapper/smbw_dir.c deleted file mode 100644 index 31d81a1e7e..0000000000 --- a/source4/smbwrapper/smbw_dir.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper directory functions - Copyright (C) Andrew Tridgell 1998 - - 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 "realcalls.h" - -extern pstring smbw_cwd; -extern fstring smbw_prefix; - -static struct smbw_dir *smbw_dirs; - -extern struct bitmap *smbw_file_bmap; - -extern int smbw_busy; - -/***************************************************** -map a fd to a smbw_dir structure -*******************************************************/ -struct smbw_dir *smbw_dir(int fd) -{ - struct smbw_dir *dir; - - for (dir=smbw_dirs;dir;dir=dir->next) { - if (dir->fd == fd) return dir; - } - return NULL; -} - -/***************************************************** -check if a DIR* is one of ours -*******************************************************/ -int smbw_dirp(DIR *dirp) -{ - struct smbw_dir *d = (struct smbw_dir *)dirp; - struct smbw_dir *dir; - - for (dir=smbw_dirs;dir;dir=dir->next) { - if (dir == d) return 1; - } - return 0; -} - -/***************************************************** -free a smbw_dir structure and all entries -*******************************************************/ -static void free_dir(struct smbw_dir *dir) -{ - if(!dir) return; - - SAFE_FREE(dir->list); - SAFE_FREE(dir->path); - ZERO_STRUCTP(dir); - SAFE_FREE(dir); -} - -static struct smbw_dir *cur_dir; - -/***************************************************** -add a entry to a directory listing -*******************************************************/ -static void smbw_dir_add(struct file_info *finfo, const char *mask, - void *state) -{ - struct file_info *cdl; - - DEBUG(5,("%s\n", finfo->name)); - - if (cur_dir->malloced == cur_dir->count) { - cdl = (struct file_info *)Realloc(cur_dir->list, - sizeof(cur_dir->list[0])* - (cur_dir->count+100)); - if (!cdl) { - /* oops */ - return; - } - cur_dir->list = cdl; - cur_dir->malloced += 100; - } - - cur_dir->list[cur_dir->count] = *finfo; - cur_dir->count++; -} - -/***************************************************** -add a entry to a directory listing -*******************************************************/ -static void smbw_share_add(const char *share, uint32 type, - const char *comment, void *state) -{ - struct file_info finfo; - - if (strcmp(share,"IPC$") == 0) return; - - ZERO_STRUCT(finfo); - - pstrcpy(finfo.name, share); - finfo.mode = aRONLY | aDIR; - - smbw_dir_add(&finfo, NULL, NULL); -} - - -/***************************************************** -add a server to a directory listing -*******************************************************/ -static void smbw_server_add(const char *name, uint32 type, - const char *comment, void *state) -{ - struct file_info finfo; - - ZERO_STRUCT(finfo); - - pstrcpy(finfo.name, name); - finfo.mode = aRONLY | aDIR; - - smbw_dir_add(&finfo, NULL, NULL); -} - - -/***************************************************** -add a entry to a directory listing -*******************************************************/ -static void smbw_printjob_add(struct print_job_info *job) -{ - struct file_info finfo; - - ZERO_STRUCT(finfo); - - pstrcpy(finfo.name, job->name); - finfo.mode = aRONLY | aDIR; - finfo.mtime = job->t; - finfo.atime = job->t; - finfo.ctime = job->t; - finfo.uid = nametouid(job->user); - finfo.mode = aRONLY; - finfo.size = job->size; - - smbw_dir_add(&finfo, NULL, NULL); -} - - -/***************************************************** -open a directory on the server -*******************************************************/ -int smbw_dir_open(const char *fname) -{ - fstring server, share; - pstring path; - struct smbw_server *srv=NULL; - struct smbw_dir *dir=NULL; - pstring mask; - int fd; - char *s, *p; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - /* work out what server they are after */ - s = smbw_parse_path(fname, server, share, path); - - DEBUG(4,("dir_open share=%s\n", share)); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - dir = (struct smbw_dir *)malloc(sizeof(*dir)); - if (!dir) { - errno = ENOMEM; - goto failed; - } - - ZERO_STRUCTP(dir); - - cur_dir = dir; - - slprintf(mask, sizeof(mask)-1, "%s\\*", path); - all_string_sub(mask,"\\\\","\\",0); - - if ((p=strstr(srv->server_name,"#01"))) { - *p = 0; - smbw_server_add(".",0,"", NULL); - smbw_server_add("..",0,"", NULL); - smbw_NetServerEnum(&srv->cli, srv->server_name, - SV_TYPE_DOMAIN_ENUM, smbw_server_add, NULL); - *p = '#'; - } else if ((p=strstr(srv->server_name,"#1D"))) { - DEBUG(4,("doing NetServerEnum\n")); - *p = 0; - smbw_server_add(".",0,"", NULL); - smbw_server_add("..",0,"", NULL); - smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL, - smbw_server_add, NULL); - *p = '#'; - } else if (strcmp(srv->cli.dev,"IPC") == 0) { - DEBUG(4,("doing NetShareEnum\n")); - smbw_share_add(".",0,"", NULL); - smbw_share_add("..",0,"", NULL); - if (smbw_RNetShareEnum(&srv->cli, smbw_share_add, NULL) < 0) { - errno = smbw_errno(&srv->cli); - goto failed; - } - } else if (strncmp(srv->cli.dev,"LPT",3) == 0) { - smbw_share_add(".",0,"", NULL); - smbw_share_add("..",0,"", NULL); - if (cli_print_queue(&srv->cli, smbw_printjob_add) < 0) { - errno = smbw_errno(&srv->cli); - goto failed; - } - } else { -#if 0 - if (strcmp(path,"\\") == 0) { - smbw_share_add(".",0,""); - smbw_share_add("..",0,""); - } -#endif - if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR, - smbw_dir_add, NULL) < 0) { - errno = smbw_errno(&srv->cli); - goto failed; - } - } - - cur_dir = NULL; - - fd = open(SMBW_DUMMY, O_WRONLY); - if (fd == -1) { - errno = EMFILE; - goto failed; - } - - if (bitmap_query(smbw_file_bmap, fd)) { - DEBUG(0,("ERROR: fd used in smbw_dir_open\n")); - errno = EIO; - goto failed; - } - - DLIST_ADD(smbw_dirs, dir); - - bitmap_set(smbw_file_bmap, fd); - - dir->fd = fd; - dir->srv = srv; - dir->path = strdup(s); - - DEBUG(4,(" -> %d\n", dir->count)); - - return dir->fd; - - failed: - free_dir(dir); - - return -1; -} - -/***************************************************** -a wrapper for fstat() on a directory -*******************************************************/ -int smbw_dir_fstat(int fd, struct stat *st) -{ - struct smbw_dir *dir; - - dir = smbw_dir(fd); - if (!dir) { - errno = EBADF; - return -1; - } - - ZERO_STRUCTP(st); - - smbw_setup_stat(st, "", dir->count*DIRP_SIZE, aDIR); - - st->st_dev = dir->srv->dev; - - return 0; -} - -/***************************************************** -close a directory handle -*******************************************************/ -int smbw_dir_close(int fd) -{ - struct smbw_dir *dir; - - dir = smbw_dir(fd); - if (!dir) { - errno = EBADF; - return -1; - } - - bitmap_clear(smbw_file_bmap, dir->fd); - close(dir->fd); - - DLIST_REMOVE(smbw_dirs, dir); - - free_dir(dir); - - return 0; -} - -/***************************************************** -a wrapper for getdents() -*******************************************************/ -int smbw_getdents(unsigned int fd, struct dirent *dirp, int count) -{ - struct smbw_dir *dir; - int n=0; - - smbw_busy++; - - dir = smbw_dir(fd); - if (!dir) { - errno = EBADF; - smbw_busy--; - return -1; - } - - while (count>=DIRP_SIZE && (dir->offset < dir->count)) { -#if HAVE_DIRENT_D_OFF - dirp->d_off = (dir->offset+1)*DIRP_SIZE; -#endif - dirp->d_reclen = DIRP_SIZE; - fstrcpy(&dirp->d_name[0], dir->list[dir->offset].name); - dirp->d_ino = smbw_inode(dir->list[dir->offset].name); - dir->offset++; - count -= dirp->d_reclen; -#if HAVE_DIRENT_D_OFF - if (dir->offset == dir->count) { - dirp->d_off = -1; - } -#endif - dirp = (struct dirent *)(((char *)dirp) + DIRP_SIZE); - n++; - } - - smbw_busy--; - return n*DIRP_SIZE; -} - - -/***************************************************** -a wrapper for chdir() -*******************************************************/ -int smbw_chdir(const char *name) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - uint16 mode = aDIR; - char *cwd; - int len; - - smbw_init(); - - len = strlen(smbw_prefix); - - if (smbw_busy) return real_chdir(name); - - smbw_busy++; - - if (!name) { - errno = EINVAL; - goto failed; - } - - DEBUG(4,("smbw_chdir(%s)\n", name)); - - /* work out what server they are after */ - cwd = smbw_parse_path(name, server, share, path); - - /* a special case - accept cd to /smb */ - if (strncmp(cwd, smbw_prefix, len-1) == 0 && - cwd[len-1] == 0) { - goto success1; - } - - if (strncmp(cwd,smbw_prefix,strlen(smbw_prefix))) { - if (real_chdir(cwd) == 0) { - goto success2; - } - goto failed; - } - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (strncmp(srv->cli.dev,"IPC",3) && - strncmp(srv->cli.dev,"LPT",3) && - !smbw_getatr(srv, path, - &mode, NULL, NULL, NULL, NULL, NULL)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - if (!(mode & aDIR)) { - errno = ENOTDIR; - goto failed; - } - - success1: - /* we don't want the old directory to be busy */ - real_chdir("/"); - - success2: - - DEBUG(4,("set SMBW_CWD to %s\n", cwd)); - - pstrcpy(smbw_cwd, cwd); - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for lseek() on directories -*******************************************************/ -off_t smbw_dir_lseek(int fd, off_t offset, int whence) -{ - struct smbw_dir *dir; - off_t ret; - - dir = smbw_dir(fd); - if (!dir) { - errno = EBADF; - return -1; - } - - switch (whence) { - case SEEK_SET: - dir->offset = offset/DIRP_SIZE; - break; - case SEEK_CUR: - dir->offset += offset/DIRP_SIZE; - break; - case SEEK_END: - dir->offset = (dir->count * DIRP_SIZE) + offset; - dir->offset /= DIRP_SIZE; - break; - } - - ret = dir->offset * DIRP_SIZE; - - DEBUG(4,(" -> %d\n", (int)ret)); - - return ret; -} - - -/***************************************************** -a wrapper for mkdir() -*******************************************************/ -int smbw_mkdir(const char *fname, mode_t mode) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_mkdir(&srv->cli, path)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - -/***************************************************** -a wrapper for rmdir() -*******************************************************/ -int smbw_rmdir(const char *fname) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - - if (!fname) { - errno = EINVAL; - return -1; - } - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - /* smbw_server sets errno */ - goto failed; - } - - if (!cli_rmdir(&srv->cli, path)) { - errno = smbw_errno(&srv->cli); - goto failed; - } - - smbw_busy--; - return 0; - - failed: - smbw_busy--; - return -1; -} - - -/***************************************************** -a wrapper for getcwd() -*******************************************************/ -char *smbw_getcwd(char *buf, size_t size) -{ - smbw_init(); - - if (smbw_busy) { - return (char *)real_getcwd(buf, size); - } - - smbw_busy++; - - if (!buf) { - if (size <= 0) size = strlen(smbw_cwd)+1; - buf = (char *)malloc(size); - if (!buf) { - errno = ENOMEM; - smbw_busy--; - return NULL; - } - } - - if (strlen(smbw_cwd) > size-1) { - errno = ERANGE; - smbw_busy--; - return NULL; - } - - safe_strcpy(buf, smbw_cwd, size); - - smbw_busy--; - return buf; -} - -/***************************************************** -a wrapper for fchdir() -*******************************************************/ -int smbw_fchdir(unsigned int fd) -{ - struct smbw_dir *dir; - int ret; - - smbw_busy++; - - dir = smbw_dir(fd); - if (dir) { - smbw_busy--; - return chdir(dir->path); - } - - ret = real_fchdir(fd); - if (ret == 0) { - sys_getwd(smbw_cwd); - } - - smbw_busy--; - return ret; -} - -/***************************************************** -open a directory on the server -*******************************************************/ -DIR *smbw_opendir(const char *fname) -{ - int fd; - - smbw_busy++; - - fd = smbw_dir_open(fname); - - if (fd == -1) { - smbw_busy--; - return NULL; - } - - smbw_busy--; - - return (DIR *)smbw_dir(fd); -} - -/***************************************************** -read one entry from a directory -*******************************************************/ -struct dirent *smbw_readdir(DIR *dirp) -{ - struct smbw_dir *d = (struct smbw_dir *)dirp; - static union { - char buf[DIRP_SIZE]; - struct dirent de; - } dbuf; - - if (smbw_getdents(d->fd, &dbuf.de, DIRP_SIZE) > 0) - return &dbuf.de; - - return NULL; -} - -/***************************************************** -close a DIR* -*******************************************************/ -int smbw_closedir(DIR *dirp) -{ - struct smbw_dir *d = (struct smbw_dir *)dirp; - return smbw_close(d->fd); -} - -/***************************************************** -seek in a directory -*******************************************************/ -void smbw_seekdir(DIR *dirp, off_t offset) -{ - struct smbw_dir *d = (struct smbw_dir *)dirp; - smbw_dir_lseek(d->fd,offset, SEEK_SET); -} - -/***************************************************** -current loc in a directory -*******************************************************/ -off_t smbw_telldir(DIR *dirp) -{ - struct smbw_dir *d = (struct smbw_dir *)dirp; - return smbw_dir_lseek(d->fd,0,SEEK_CUR); -} diff --git a/source4/smbwrapper/smbw_stat.c b/source4/smbwrapper/smbw_stat.c deleted file mode 100644 index 6c476a8a67..0000000000 --- a/source4/smbwrapper/smbw_stat.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper stat functions - Copyright (C) Andrew Tridgell 1998 - - 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" - -extern int smbw_busy; - -/***************************************************** -setup basic info in a stat structure -*******************************************************/ -void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode) -{ - st->st_mode = 0; - - if (IS_DOS_DIR(mode)) { - st->st_mode = SMBW_DIR_MODE; - } else { - st->st_mode = SMBW_FILE_MODE; - } - - if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR; - if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP; - if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH; - if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR; - - st->st_size = size; - st->st_blksize = 512; - st->st_blocks = (size+511)/512; - st->st_uid = getuid(); - st->st_gid = getgid(); - if (IS_DOS_DIR(mode)) { - st->st_nlink = 2; - } else { - st->st_nlink = 1; - } - if (st->st_ino == 0) { - st->st_ino = smbw_inode(fname); - } -} - - -/***************************************************** -try to do a QPATHINFO and if that fails then do a getatr -this is needed because win95 sometimes refuses the qpathinfo -*******************************************************/ -BOOL smbw_getatr(struct smbw_server *srv, char *path, - uint16 *mode, size_t *size, - time_t *c_time, time_t *a_time, time_t *m_time, - SMB_INO_T *ino) -{ - DEBUG(4,("sending qpathinfo\n")); - - if (!srv->no_pathinfo2 && - cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL, - size, mode, ino)) return True; - - /* if this is NT then don't bother with the getatr */ - if (srv->cli.capabilities & CAP_NT_SMBS) return False; - - if (cli_getatr(&srv->cli, path, mode, size, m_time)) { - a_time = c_time = m_time; - srv->no_pathinfo2 = True; - return True; - } - return False; -} - - -static struct print_job_info printjob; - -/***************************************************** -gather info from a printjob listing -*******************************************************/ -static void smbw_printjob_stat(struct print_job_info *job) -{ - if (strcmp(job->name, printjob.name) == 0) { - printjob = *job; - } -} - -/***************************************************** -stat a printjob -*******************************************************/ -int smbw_stat_printjob(struct smbw_server *srv,char *path, - size_t *size, time_t *m_time) -{ - if (path[0] == '\\') path++; - - ZERO_STRUCT(printjob); - - fstrcpy(printjob.name, path); - cli_print_queue(&srv->cli, smbw_printjob_stat); - - if (size) { - *size = printjob.size; - } - if (m_time) { - *m_time = printjob.t; - } - return printjob.id; -} - - -/***************************************************** -a wrapper for fstat() -*******************************************************/ -int smbw_fstat(int fd, struct stat *st) -{ - struct smbw_file *file; - time_t c_time, a_time, m_time; - size_t size; - uint16 mode; - SMB_INO_T ino = 0; - - smbw_busy++; - - ZERO_STRUCTP(st); - - file = smbw_file(fd); - if (!file) { - int ret = smbw_dir_fstat(fd, st); - smbw_busy--; - return ret; - } - - if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, - &mode, &size, &c_time, &a_time, &m_time, NULL, - &ino) && - !cli_getattrE(&file->srv->cli, file->f->cli_fd, - &mode, &size, &c_time, &a_time, &m_time)) { - errno = EINVAL; - smbw_busy--; - return -1; - } - - st->st_ino = ino; - - smbw_setup_stat(st, file->f->fname, size, mode); - - st->st_atime = a_time; - st->st_ctime = c_time; - st->st_mtime = m_time; - st->st_dev = file->srv->dev; - - smbw_busy--; - return 0; -} - - -/***************************************************** -a wrapper for stat() -*******************************************************/ -int smbw_stat(const char *fname, struct stat *st) -{ - struct smbw_server *srv; - fstring server, share; - pstring path; - time_t m_time=0, a_time=0, c_time=0; - size_t size=0; - uint16 mode=0; - SMB_INO_T ino = 0; - int result = 0; - - ZERO_STRUCTP(st); - - if (!fname) { - errno = EINVAL; - return -1; - } - - DEBUG(4,("stat(%s)\n", fname)); - - smbw_init(); - - smbw_busy++; - - /* work out what server they are after */ - smbw_parse_path(fname, server, share, path); - - /* get a connection to the server */ - srv = smbw_server(server, share); - if (!srv) { - - /* For shares we aren't allowed to connect to, or no master - browser found, return an empty directory */ - - if ((server[0] && share[0] && !path[0] && errno == EACCES) || - (!path[0] && errno == ENOENT)) { - mode = aDIR | aRONLY; - smbw_setup_stat(st, path, size, mode); - goto done; - } - - /* smbw_server sets errno */ - result = -1; - goto done; - } - - DEBUG(4,("smbw_stat\n")); - - if (strncmp(srv->cli.dev,"IPC",3) == 0) { - mode = aDIR | aRONLY; - } else if (strncmp(srv->cli.dev,"LPT",3) == 0) { - if (strcmp(path,"\\") == 0) { - mode = aDIR | aRONLY; - } else { - mode = aRONLY; - smbw_stat_printjob(srv, path, &size, &m_time); - c_time = a_time = m_time; - } - } else { - if (!smbw_getatr(srv, path, - &mode, &size, &c_time, &a_time, &m_time, - &ino)) { - errno = smbw_errno(&srv->cli); - result = -1; - goto done; - } - } - - st->st_ino = ino; - - smbw_setup_stat(st, path, size, mode); - - st->st_atime = a_time; - st->st_ctime = c_time; - st->st_mtime = m_time; - st->st_dev = srv->dev; - - done: - smbw_busy--; - return result; -} diff --git a/source4/smbwrapper/wrapped.c b/source4/smbwrapper/wrapped.c deleted file mode 100644 index 338ee0d5b1..0000000000 --- a/source4/smbwrapper/wrapped.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMB wrapper functions - Copyright (C) Andrew Tridgell 1998 - - 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. -*/ - -/* NOTE: This file WILL produce compiler warnings. They are unavoidable - - Do not try and get rid of them by including other include files or - by including includes.h or proto.h or you will break portability. - */ - -#include "config.h" -#include <sys/types.h> -#include <errno.h> -#include "realcalls.h" - -#ifndef NULL -# define NULL ((void *)0) -#endif - - int open(char *name, int flags, mode_t mode) -{ - if (smbw_path(name)) { - return smbw_open(name, flags, mode); - } - - return real_open(name, flags, mode); -} - -#ifdef HAVE__OPEN - int _open(char *name, int flags, mode_t mode) -{ - return open(name, flags, mode); -} -#elif HAVE___OPEN - int __open(char *name, int flags, mode_t mode) -{ - return open(name, flags, mode); -} -#endif - - -#ifdef HAVE_OPEN64 - int open64(char *name, int flags, mode_t mode) -{ - if (smbw_path(name)) { - return smbw_open(name, flags, mode); - } - - return real_open64(name, flags, mode); -} -#endif - -#ifndef NO_OPEN64_ALIAS -#ifdef HAVE__OPEN64 - int _open64(char *name, int flags, mode_t mode) -{ - return open64(name, flags, mode); -} -#elif HAVE___OPEN64 - int __open64(char *name, int flags, mode_t mode) -{ - return open64(name, flags, mode); -} -#endif -#endif - -#ifdef HAVE_PREAD - ssize_t pread(int fd, void *buf, size_t size, off_t ofs) -{ - if (smbw_fd(fd)) { - return smbw_pread(fd, buf, size, ofs); - } - - return real_pread(fd, buf, size, ofs); -} -#endif - -#if defined(HAVE_PREAD64) && defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) - ssize_t pread64(int fd, void *buf, size_t size, off64_t ofs) -{ - if (smbw_fd(fd)) { - return smbw_pread(fd, buf, size, ofs); - } - - return real_pread64(fd, buf, size, ofs); -} -#endif - -#ifdef HAVE_PWRITE - ssize_t pwrite(int fd, void *buf, size_t size, off_t ofs) -{ - if (smbw_fd(fd)) { - return smbw_pwrite(fd, buf, size, ofs); - } - - return real_pwrite(fd, buf, size, ofs); -} -#endif - -#if defined(HAVE_PWRITE64) && defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) - ssize_t pwrite64(int fd, void *buf, size_t size, off64_t ofs) -{ - if (smbw_fd(fd)) { - return smbw_pwrite(fd, buf, size, ofs); - } - - return real_pwrite64(fd, buf, size, ofs); -} -#endif - - - int chdir(char *name) -{ - return smbw_chdir(name); -} - -#ifdef HAVE___CHDIR - int __chdir(char *name) -{ - return chdir(name); -} -#elif HAVE__CHDIR - int _chdir(char *name) -{ - return chdir(name); -} -#endif - - - int close(int fd) -{ - if (smbw_fd(fd)) { - return smbw_close(fd); - } - if (smbw_local_fd(fd)) { - errno = EBADF; - return -1; - } - - return real_close(fd); -} - -#ifdef HAVE___CLOSE - int __close(int fd) -{ - return close(fd); -} -#elif HAVE__CLOSE - int _close(int fd) -{ - return close(fd); -} -#endif - - - int fchdir(int fd) -{ - return smbw_fchdir(fd); -} - -#ifdef HAVE___FCHDIR - int __fchdir(int fd) -{ - return fchdir(fd); -} -#elif HAVE__FCHDIR - int _fchdir(int fd) -{ - return fchdir(fd); -} -#endif - - - int fcntl(int fd, int cmd, long arg) -{ - if (smbw_fd(fd)) { - return smbw_fcntl(fd, cmd, arg); - } - - return real_fcntl(fd, cmd, arg); -} - - -#ifdef HAVE___FCNTL - int __fcntl(int fd, int cmd, long arg) -{ - return fcntl(fd, cmd, arg); -} -#elif HAVE__FCNTL - int _fcntl(int fd, int cmd, long arg) -{ - return fcntl(fd, cmd, arg); -} -#endif - - - -#ifdef real_getdents - int getdents(int fd, void *dirp, unsigned int count) -{ - if (smbw_fd(fd)) { - return smbw_getdents(fd, dirp, count); - } - - return real_getdents(fd, dirp, count); -} -#endif - -#ifdef HAVE___GETDENTS - int __getdents(int fd, void *dirp, unsigned int count) -{ - return getdents(fd, dirp, count); -} -#elif HAVE__GETDENTS - int _getdents(int fd, void *dirp, unsigned int count) -{ - return getdents(fd, dirp, count); -} -#endif - - - off_t lseek(int fd, off_t offset, int whence) -{ - if (smbw_fd(fd)) { - return smbw_lseek(fd, offset, whence); - } - - return real_lseek(fd, offset, whence); -} - -#ifdef HAVE___LSEEK - off_t __lseek(int fd, off_t offset, int whence) -{ - return lseek(fd, offset, whence); -} -#elif HAVE__LSEEK - off_t _lseek(int fd, off_t offset, int whence) -{ - return lseek(fd, offset, whence); -} -#endif - - - ssize_t read(int fd, void *buf, size_t count) -{ - if (smbw_fd(fd)) { - return smbw_read(fd, buf, count); - } - - return real_read(fd, buf, count); -} - -#ifdef HAVE___READ - ssize_t __read(int fd, void *buf, size_t count) -{ - return read(fd, buf, count); -} -#elif HAVE__READ - ssize_t _read(int fd, void *buf, size_t count) -{ - return read(fd, buf, count); -} -#endif - - - ssize_t write(int fd, void *buf, size_t count) -{ - if (smbw_fd(fd)) { - return smbw_write(fd, buf, count); - } - - return real_write(fd, buf, count); -} - -#ifdef HAVE___WRITE - ssize_t __write(int fd, void *buf, size_t count) -{ - return write(fd, buf, count); -} -#elif HAVE__WRITE - ssize_t _write(int fd, void *buf, size_t count) -{ - return write(fd, buf, count); -} -#endif - - - - int access(char *name, int mode) -{ - if (smbw_path(name)) { - return smbw_access(name, mode); - } - - return real_access(name, mode); -} - - - - int chmod(char *name,mode_t mode) -{ - if (smbw_path(name)) { - return smbw_chmod(name, mode); - } - - return real_chmod(name, mode); -} - - - - int chown(char *name,uid_t owner, gid_t group) -{ - if (smbw_path(name)) { - return smbw_chown(name, owner, group); - } - - return real_chown(name, owner, group); -} - - - char *getcwd(char *buf, size_t size) -{ - return (char *)smbw_getcwd(buf, size); -} - - - - - int mkdir(char *name, mode_t mode) -{ - if (smbw_path(name)) { - return smbw_mkdir(name, mode); - } - - return real_mkdir(name, mode); -} - - -#if HAVE___FXSTAT - int __fxstat(int vers, int fd, void *st) -{ - double xx[32]; - int ret; - - if (smbw_fd(fd)) { - return smbw_fstat(fd, st); - } - - ret = real_fstat(fd, xx); - xstat_convert(vers, st, xx); - return ret; -} -#endif - -#if HAVE___XSTAT - int __xstat(int vers, char *name, void *st) -{ - double xx[32]; - int ret; - - if (smbw_path(name)) { - return smbw_stat(name, st); - } - - ret = real_stat(name, xx); - xstat_convert(vers, st, xx); - return ret; -} -#endif - - -#if HAVE___LXSTAT - int __lxstat(int vers, char *name, void *st) -{ - double xx[32]; - int ret; - - if (smbw_path(name)) { - return smbw_stat(name, st); - } - - ret = real_lstat(name, xx); - xstat_convert(vers, st, xx); - return ret; -} -#endif - - - int stat(char *name, void *st) -{ -#if HAVE___XSTAT - return __xstat(0, name, st); -#else - if (smbw_path(name)) { - return smbw_stat(name, st); - } - return real_stat(name, st); -#endif -} - - int lstat(char *name, void *st) -{ -#if HAVE___LXSTAT - return __lxstat(0, name, st); -#else - if (smbw_path(name)) { - return smbw_stat(name, st); - } - return real_lstat(name, st); -#endif -} - - int fstat(int fd, void *st) -{ -#if HAVE___LXSTAT - return __fxstat(0, fd, st); -#else - if (smbw_fd(fd)) { - return smbw_fstat(fd, st); - } - return real_fstat(fd, st); -#endif -} - - - int unlink(char *name) -{ - if (smbw_path(name)) { - return smbw_unlink(name); - } - - return real_unlink(name); -} - - -#ifdef HAVE_UTIME - int utime(char *name,void *tvp) -{ - if (smbw_path(name)) { - return smbw_utime(name, tvp); - } - - return real_utime(name, tvp); -} -#endif - -#ifdef HAVE_UTIMES - int utimes(const char *name, const struct timeval *tvp) -{ - if (smbw_path(name)) { - return smbw_utimes(name, tvp); - } - - return real_utimes(name, tvp); -} -#endif - - int readlink(char *path, char *buf, size_t bufsize) -{ - if (smbw_path(path)) { - return smbw_readlink(path, buf, bufsize); - } - - return real_readlink(path, buf, bufsize); -} - - - int rename(char *oldname,char *newname) -{ - int p1, p2; - p1 = smbw_path(oldname); - p2 = smbw_path(newname); - if (p1 ^ p2) { - /* can't cross filesystem boundaries */ - errno = EXDEV; - return -1; - } - if (p1 && p2) { - return smbw_rename(oldname, newname); - } - - return real_rename(oldname, newname); -} - - int rmdir(char *name) -{ - if (smbw_path(name)) { - return smbw_rmdir(name); - } - - return real_rmdir(name); -} - - - int symlink(char *topath,char *frompath) -{ - int p1, p2; - p1 = smbw_path(topath); - p2 = smbw_path(frompath); - if (p1 || p2) { - /* can't handle symlinks */ - errno = EPERM; - return -1; - } - - return real_symlink(topath, frompath); -} - - int dup(int fd) -{ - if (smbw_fd(fd)) { - return smbw_dup(fd); - } - - return real_dup(fd); -} - - int dup2(int oldfd, int newfd) -{ - if (smbw_fd(newfd)) { - close(newfd); - } - - if (smbw_fd(oldfd)) { - return smbw_dup2(oldfd, newfd); - } - - return real_dup2(oldfd, newfd); -} - -#ifdef real_opendir - void *opendir(char *name) -{ - if (smbw_path(name)) { - return (void *)smbw_opendir(name); - } - - return (void *)real_opendir(name); -} -#endif - -#ifdef real_readdir - void *readdir(void *dir) -{ - if (smbw_dirp(dir)) { - return (void *)smbw_readdir(dir); - } - - return (void *)real_readdir(dir); -} -#endif - -#ifdef real_closedir - int closedir(void *dir) -{ - if (smbw_dirp(dir)) { - return smbw_closedir(dir); - } - - return real_closedir(dir); -} -#endif - -#ifdef real_telldir - off_t telldir(void *dir) -{ - if (smbw_dirp(dir)) { - return smbw_telldir(dir); - } - - return real_telldir(dir); -} -#endif - -#ifdef real_seekdir - int seekdir(void *dir, off_t offset) -{ - if (smbw_dirp(dir)) { - smbw_seekdir(dir, offset); - return 0; - } - - real_seekdir(dir, offset); - return 0; -} -#endif - - -#ifndef NO_ACL_WRAPPER - int acl(char *pathp, int cmd, int nentries, void *aclbufp) -{ - if (smbw_path(pathp)) { - return smbw_acl(pathp, cmd, nentries, aclbufp); - } - - return real_acl(pathp, cmd, nentries, aclbufp); -} -#endif - -#ifndef NO_FACL_WRAPPER - int facl(int fd, int cmd, int nentries, void *aclbufp) -{ - if (smbw_fd(fd)) { - return smbw_facl(fd, cmd, nentries, aclbufp); - } - - return real_facl(fd, cmd, nentries, aclbufp); -} -#endif - - int creat(char *path, mode_t mode) -{ - extern int creat_bits; - return open(path, creat_bits, mode); -} - -#ifdef HAVE_CREAT64 - int creat64(char *path, mode_t mode) -{ - extern int creat_bits; - return open64(path, creat_bits, mode); -} -#endif - -#ifdef HAVE_STAT64 - int stat64(char *name, void *st64) -{ - if (smbw_path(name)) { - double xx[32]; - int ret = stat(name, xx); - stat64_convert(xx, st64); - return ret; - } - return real_stat64(name, st64); -} - - int fstat64(int fd, void *st64) -{ - if (smbw_fd(fd)) { - double xx[32]; - int ret = fstat(fd, xx); - stat64_convert(xx, st64); - return ret; - } - return real_fstat64(fd, st64); -} - - int lstat64(char *name, void *st64) -{ - if (smbw_path(name)) { - double xx[32]; - int ret = lstat(name, xx); - stat64_convert(xx, st64); - return ret; - } - return real_lstat64(name, st64); -} -#endif - -#ifdef HAVE_LLSEEK - offset_t llseek(int fd, offset_t ofs, int whence) -{ - if (smbw_fd(fd)) { - return lseek(fd, ofs, whence); - } - return real_llseek(fd, ofs, whence); -} -#endif - -#ifdef HAVE_READDIR64 - void *readdir64(void *dir) -{ - if (smbw_dirp(dir)) { - static double xx[70]; - void *d; - d = (void *)readdir(dir); - if (!d) return NULL; - dirent64_convert(d, xx); - return xx; - } - return (void *)real_readdir64(dir); -} -#endif - - int fork(void) -{ - return smbw_fork(); -} - diff --git a/source4/web/cgi.c b/source4/web/cgi.c deleted file mode 100644 index f755bb22e9..0000000000 --- a/source4/web/cgi.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - some simple CGI helper routines - Copyright (C) Andrew Tridgell 1997-1998 - - 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" - -#define MAX_VARIABLES 10000 - -/* set the expiry on fixed pages */ -#define EXPIRY_TIME (60*60*24*7) - -#ifdef DEBUG_COMMENTS -extern void print_title(char *fmt, ...); -#endif - -struct var { - char *name; - char *value; -}; - -static struct var variables[MAX_VARIABLES]; -static int num_variables; -static int content_length; -static int request_post; -static char *query_string; -static const char *baseurl; -static char *pathinfo; -static char *C_user; -static BOOL inetd_server; -static BOOL got_request; - -static char *grab_line(FILE *f, int *cl) -{ - char *ret = NULL; - int i = 0; - int len = 0; - - while ((*cl)) { - int c; - - if (i == len) { - char *ret2; - if (len == 0) len = 1024; - else len *= 2; - ret2 = (char *)Realloc(ret, len); - if (!ret2) return ret; - ret = ret2; - } - - c = fgetc(f); - (*cl)--; - - if (c == EOF) { - (*cl) = 0; - break; - } - - if (c == '\r') continue; - - if (strchr_m("\n&", c)) break; - - ret[i++] = c; - - } - - - ret[i] = 0; - return ret; -} - -/*************************************************************************** - load all the variables passed to the CGI program. May have multiple variables - with the same name and the same or different values. Takes a file parameter - for simulating CGI invocation eg loading saved preferences. - ***************************************************************************/ -void cgi_load_variables(void) -{ - static char *line; - char *p, *s, *tok; - int len, i; - FILE *f = stdin; - -#ifdef DEBUG_COMMENTS - char dummy[100]=""; - print_title(dummy); - d_printf("<!== Start dump in cgi_load_variables() %s ==>\n",__FILE__); -#endif - - if (!content_length) { - p = getenv("CONTENT_LENGTH"); - len = p?atoi(p):0; - } else { - len = content_length; - } - - - if (len > 0 && - (request_post || - ((s=getenv("REQUEST_METHOD")) && - strcasecmp(s,"POST")==0))) { - while (len && (line=grab_line(f, &len))) { - p = strchr_m(line,'='); - if (!p) continue; - - *p = 0; - - variables[num_variables].name = strdup(line); - variables[num_variables].value = strdup(p+1); - - SAFE_FREE(line); - - if (!variables[num_variables].name || - !variables[num_variables].value) - continue; - - rfc1738_unescape(variables[num_variables].value); - rfc1738_unescape(variables[num_variables].name); - -#ifdef DEBUG_COMMENTS - printf("<!== POST var %s has value \"%s\" ==>\n", - variables[num_variables].name, - variables[num_variables].value); -#endif - - num_variables++; - if (num_variables == MAX_VARIABLES) break; - } - } - - fclose(stdin); - open("/dev/null", O_RDWR); - - if ((s=query_string) || (s=getenv("QUERY_STRING"))) { - for (tok=strtok(s,"&;");tok;tok=strtok(NULL,"&;")) { - p = strchr_m(tok,'='); - if (!p) continue; - - *p = 0; - - variables[num_variables].name = strdup(tok); - variables[num_variables].value = strdup(p+1); - - if (!variables[num_variables].name || - !variables[num_variables].value) - continue; - - rfc1738_unescape(variables[num_variables].value); - rfc1738_unescape(variables[num_variables].name); - -#ifdef DEBUG_COMMENTS - printf("<!== Commandline var %s has value \"%s\" ==>\n", - variables[num_variables].name, - variables[num_variables].value); -#endif - num_variables++; - if (num_variables == MAX_VARIABLES) break; - } - - } -#ifdef DEBUG_COMMENTS - printf("<!== End dump in cgi_load_variables() ==>\n"); -#endif - - /* variables from the client are in display charset - convert them - to our internal charset before use */ - for (i=0;i<num_variables;i++) { - pstring dest; - - convert_string(CH_DISPLAY, CH_UNIX, - variables[i].name, -1, - dest, sizeof(dest)); - free(variables[i].name); - variables[i].name = strdup(dest); - - convert_string(CH_DISPLAY, CH_UNIX, - variables[i].value, -1, - dest, sizeof(dest)); - free(variables[i].value); - variables[i].value = strdup(dest); - } -} - - -/*************************************************************************** - find a variable passed via CGI - Doesn't quite do what you think in the case of POST text variables, because - if they exist they might have a value of "" or even " ", depending on the - browser. Also doesn't allow for variables[] containing multiple variables - with the same name and the same or different values. - ***************************************************************************/ -const char *cgi_variable(const char *name) -{ - int i; - - for (i=0;i<num_variables;i++) - if (strcmp(variables[i].name, name) == 0) - return variables[i].value; - return NULL; -} - -/*************************************************************************** -tell a browser about a fatal error in the http processing - ***************************************************************************/ -static void cgi_setup_error(const char *err, const char *header, const char *info) -{ - if (!got_request) { - /* damn browsers don't like getting cut off before they give a request */ - char line[1024]; - while (fgets(line, sizeof(line)-1, stdin)) { - if (strncasecmp(line,"GET ", 4)==0 || - strncasecmp(line,"POST ", 5)==0 || - strncasecmp(line,"PUT ", 4)==0) { - break; - } - } - } - - d_printf("HTTP/1.0 %s\r\n%sConnection: close\r\nContent-Type: text/html\r\n\r\n<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>%s</H1>%s<p></BODY></HTML>\r\n\r\n", err, header, err, err, info); - fclose(stdin); - fclose(stdout); - exit(0); -} - - -/*************************************************************************** -tell a browser about a fatal authentication error - ***************************************************************************/ -static void cgi_auth_error(void) -{ - if (inetd_server) { - cgi_setup_error("401 Authorization Required", - "WWW-Authenticate: Basic realm=\"SWAT\"\r\n", - "You must be authenticated to use this service"); - } else { - printf("Content-Type: text/html\r\n"); - - printf("\r\n<HTML><HEAD><TITLE>SWAT</TITLE></HEAD>\n"); - printf("<BODY><H1>Installation Error</H1>\n"); - printf("SWAT must be installed via inetd. It cannot be run as a CGI script<p>\n"); - printf("</BODY></HTML>\r\n"); - } - exit(0); -} - -/*************************************************************************** -authenticate when we are running as a CGI - ***************************************************************************/ -static void cgi_web_auth(void) -{ - const char *user = getenv("REMOTE_USER"); - struct passwd *pwd; - const char *head = "Content-Type: text/html\r\n\r\n<HTML><BODY><H1>SWAT installation Error</H1>\n"; - const char *tail = "</BODY></HTML>\r\n"; - - if (!user) { - printf("%sREMOTE_USER not set. Not authenticated by web server.<br>%s\n", - head, tail); - exit(0); - } - - pwd = getpwnam_alloc(user); - if (!pwd) { - printf("%sCannot find user %s<br>%s\n", head, user, tail); - exit(0); - } - - setuid(0); - setuid(pwd->pw_uid); - if (geteuid() != pwd->pw_uid || getuid() != pwd->pw_uid) { - printf("%sFailed to become user %s - uid=%d/%d<br>%s\n", - head, user, (int)geteuid(), (int)getuid(), tail); - exit(0); - } - passwd_free(&pwd); -} - - -/*************************************************************************** -handle a http authentication line - ***************************************************************************/ -static BOOL cgi_handle_authorization(char *line) -{ - char *p; - fstring user, user_pass; - struct passwd *pass = NULL; - - if (strncasecmp(line,"Basic ", 6)) { - goto err; - } - line += 6; - while (line[0] == ' ') line++; - base64_decode_inplace(line); - if (!(p=strchr_m(line,':'))) { - /* - * Always give the same error so a cracker - * cannot tell why we fail. - */ - goto err; - } - *p = 0; - - convert_string(CH_DISPLAY, CH_UNIX, - line, -1, - user, sizeof(user)); - - convert_string(CH_DISPLAY, CH_UNIX, - p+1, -1, - user_pass, sizeof(user_pass)); - - /* - * Try and get the user from the UNIX password file. - */ - - pass = getpwnam_alloc(user); - - /* - * Validate the password they have given. - */ - - if NT_STATUS_IS_OK(pass_check(pass, user, user_pass, - strlen(user_pass), NULL, False)) { - - if (pass) { - /* - * Password was ok. - */ - - become_user_permanently(pass->pw_uid, pass->pw_gid); - - /* Save the users name */ - C_user = strdup(user); - passwd_free(&pass); - return True; - } - } - -err: - cgi_setup_error("401 Bad Authorization", "", - "username or password incorrect"); - - passwd_free(&pass); - return False; -} - -/*************************************************************************** -is this root? - ***************************************************************************/ -BOOL am_root(void) -{ - if (geteuid() == 0) { - return( True); - } else { - return( False); - } -} - -/*************************************************************************** -return a ptr to the users name - ***************************************************************************/ -char *cgi_user_name(void) -{ - return(C_user); -} - - -/*************************************************************************** -handle a file download - ***************************************************************************/ -static void cgi_download(char *file) -{ - SMB_STRUCT_STAT st; - char buf[1024]; - int fd, l, i; - char *p; - char *lang; - - /* sanitise the filename */ - for (i=0;file[i];i++) { - if (!isalnum((int)file[i]) && !strchr_m("/.-_", file[i])) { - cgi_setup_error("404 File Not Found","", - "Illegal character in filename"); - } - } - - if (!file_exist(file, &st)) { - cgi_setup_error("404 File Not Found","", - "The requested file was not found"); - } - - fd = web_open(file,O_RDONLY,0); - if (fd == -1) { - cgi_setup_error("404 File Not Found","", - "The requested file was not found"); - } - printf("HTTP/1.0 200 OK\r\n"); - if ((p=strrchr_m(file,'.'))) { - if (strcmp(p,".gif")==0) { - printf("Content-Type: image/gif\r\n"); - } else if (strcmp(p,".jpg")==0) { - printf("Content-Type: image/jpeg\r\n"); - } else if (strcmp(p,".txt")==0) { - printf("Content-Type: text/plain\r\n"); - } else { - printf("Content-Type: text/html\r\n"); - } - } - printf("Expires: %s\r\n", http_timestring(time(NULL)+EXPIRY_TIME)); - - lang = lang_tdb_current(); - if (lang) { - printf("Content-Language: %s\r\n", lang); - } - - printf("Content-Length: %d\r\n\r\n", (int)st.st_size); - while ((l=read(fd,buf,sizeof(buf)))>0) { - fwrite(buf, 1, l, stdout); - } - close(fd); - exit(0); -} - - - - -/** - * @brief Setup the CGI framework. - * - * Setup the cgi framework, handling the possibility that this program - * is either run as a true CGI program with a gateway to a web server, or - * is itself a mini web server. - **/ -void cgi_setup(const char *rootdir, int auth_required) -{ - BOOL authenticated = False; - char line[1024]; - char *url=NULL; - char *p; - char *lang; - - if (chdir(rootdir)) { - cgi_setup_error("500 Server Error", "", - "chdir failed - the server is not configured correctly"); - } - - /* Handle the possibility we might be running as non-root */ - sec_init(); - - if ((lang=getenv("HTTP_ACCEPT_LANGUAGE"))) { - /* if running as a cgi program */ - web_set_lang(lang); - } - - /* maybe we are running under a web server */ - if (getenv("CONTENT_LENGTH") || getenv("REQUEST_METHOD")) { - if (auth_required) { - cgi_web_auth(); - } - return; - } - - inetd_server = True; - - if (!check_access(1, lp_hostsallow(-1), lp_hostsdeny(-1))) { - cgi_setup_error("403 Forbidden", "", - "Samba is configured to deny access from this client\n<br>Check your \"hosts allow\" and \"hosts deny\" options in smb.conf "); - } - - /* we are a mini-web server. We need to read the request from stdin - and handle authentication etc */ - while (fgets(line, sizeof(line)-1, stdin)) { - if (line[0] == '\r' || line[0] == '\n') break; - if (strncasecmp(line,"GET ", 4)==0) { - got_request = True; - url = strdup(&line[4]); - } else if (strncasecmp(line,"POST ", 5)==0) { - got_request = True; - request_post = 1; - url = strdup(&line[5]); - } else if (strncasecmp(line,"PUT ", 4)==0) { - got_request = True; - cgi_setup_error("400 Bad Request", "", - "This server does not accept PUT requests"); - } else if (strncasecmp(line,"Authorization: ", 15)==0) { - authenticated = cgi_handle_authorization(&line[15]); - } else if (strncasecmp(line,"Content-Length: ", 16)==0) { - content_length = atoi(&line[16]); - } else if (strncasecmp(line,"Accept-Language: ", 17)==0) { - web_set_lang(&line[17]); - } - /* ignore all other requests! */ - } - - if (auth_required && !authenticated) { - cgi_auth_error(); - } - - if (!url) { - cgi_setup_error("400 Bad Request", "", - "You must specify a GET or POST request"); - } - - /* trim the URL */ - if ((p = strchr_m(url,' ')) || (p=strchr_m(url,'\t'))) { - *p = 0; - } - while (*url && strchr_m("\r\n",url[strlen(url)-1])) { - url[strlen(url)-1] = 0; - } - - /* anything following a ? in the URL is part of the query string */ - if ((p=strchr_m(url,'?'))) { - query_string = p+1; - *p = 0; - } - - string_sub(url, "/swat/", "", 0); - - if (url[0] != '/' && strstr(url,"..")==0 && file_exist(url, NULL)) { - cgi_download(url); - } - - printf("HTTP/1.0 200 OK\r\nConnection: close\r\n"); - printf("Date: %s\r\n", http_timestring(time(NULL))); - baseurl = ""; - pathinfo = url+1; -} - - -/*************************************************************************** -return the current pages URL - ***************************************************************************/ -const char *cgi_baseurl(void) -{ - if (inetd_server) { - return baseurl; - } - return getenv("SCRIPT_NAME"); -} - -/*************************************************************************** -return the current pages path info - ***************************************************************************/ -const char *cgi_pathinfo(void) -{ - char *r; - if (inetd_server) { - return pathinfo; - } - r = getenv("PATH_INFO"); - if (!r) return ""; - if (*r == '/') r++; - return r; -} - -/*************************************************************************** -return the hostname of the client - ***************************************************************************/ -char *cgi_remote_host(void) -{ - if (inetd_server) { - return get_socket_name(1,False); - } - return getenv("REMOTE_HOST"); -} - -/*************************************************************************** -return the hostname of the client - ***************************************************************************/ -char *cgi_remote_addr(void) -{ - if (inetd_server) { - return get_socket_addr(1); - } - return getenv("REMOTE_ADDR"); -} - - -/*************************************************************************** -return True if the request was a POST - ***************************************************************************/ -BOOL cgi_waspost(void) -{ - if (inetd_server) { - return request_post; - } - return strequal(getenv("REQUEST_METHOD"), "POST"); -} diff --git a/source4/web/config.m4 b/source4/web/config.m4 deleted file mode 100644 index f8bb33759d..0000000000 --- a/source4/web/config.m4 +++ /dev/null @@ -1,17 +0,0 @@ -################################################# -# set SWAT directory location -AC_ARG_WITH(swatdir, -[ --with-swatdir=DIR Where to put SWAT files ($ac_default_prefix/swat)], -[ case "$withval" in - yes|no) - # - # Just in case anybody does it - # - AC_MSG_WARN([--with-swatdir called without argument - will use default]) - ;; - * ) - swatdir="$withval" - ;; - esac]) - -AC_SUBST(swatdir) diff --git a/source4/web/diagnose.c b/source4/web/diagnose.c deleted file mode 100644 index f79d59fc6a..0000000000 --- a/source4/web/diagnose.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - Unix SMB/CIFS implementation. - diagnosis tools for web admin - Copyright (C) Andrew Tridgell 1998 - - 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" - -#ifdef WITH_WINBIND - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); - -/* check to see if winbind is running by pinging it */ - -BOOL winbindd_running(void) -{ - - if (winbindd_request(WINBINDD_PING, NULL, NULL)) - return False; - - return True; -} -#endif - -/* check to see if nmbd is running on localhost by looking for a __SAMBA__ - response */ -BOOL nmbd_running(void) -{ - extern struct in_addr loopback_ip; - int fd, count, flags; - struct in_addr *ip_list; - - if ((fd = open_socket_in(SOCK_DGRAM, 0, 3, - interpret_addr("127.0.0.1"), True)) != -1) { - if ((ip_list = name_query(fd, "__SAMBA__", 0, - True, True, loopback_ip, - &count, &flags, NULL)) != NULL) { - SAFE_FREE(ip_list); - close(fd); - return True; - } - close (fd); - } - - return False; -} - - -/* check to see if smbd is running on localhost by trying to open a connection - then closing it */ -BOOL smbd_running(void) -{ - static struct cli_state cli; - extern struct in_addr loopback_ip; - - if (!cli_initialise(&cli)) - return False; - - if (!cli_connect(&cli, lp_netbios_name(), &loopback_ip)) { - cli_shutdown(&cli); - return False; - } - - cli_shutdown(&cli); - return True; -} diff --git a/source4/web/neg_lang.c b/source4/web/neg_lang.c deleted file mode 100644 index 495596c759..0000000000 --- a/source4/web/neg_lang.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SWAT language handling - - 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. - - Created by Ryo Kawahara <rkawa@lbe.co.jp> -*/ - -#include "includes.h" - -/* - during a file download we first check to see if there is a language - specific file available. If there is then use that, otherwise - just open the specified file -*/ -int web_open(const char *fname, int flags, mode_t mode) -{ - char *p = NULL; - char *lang = lang_tdb_current(); - int fd; - if (lang) { - asprintf(&p, "lang/%s/%s", lang, fname); - if (p) { - fd = sys_open(p, flags, mode); - free(p); - if (fd != -1) { - return fd; - } - } - } - - /* fall through to default name */ - return sys_open(fname, flags, mode); -} - - -struct pri_list { - float pri; - char *string; -}; - -static int qsort_cmp_list(const void *x, const void *y) { - struct pri_list *a = (struct pri_list *)x; - struct pri_list *b = (struct pri_list *)y; - if (a->pri > b->pri) return -1; - if (a->pri == b->pri) return 0; - return 1; -} - -/* - choose from a list of languages. The list can be comma or space - separated - Keep choosing until we get a hit - Changed to habdle priority -- Simo -*/ - -void web_set_lang(const char *lang_string) -{ - char **lang_list, **count; - struct pri_list *pl; - int lang_num, i; - - /* build the lang list */ - lang_list = str_list_make(lang_string, ", \t\r\n"); - if (!lang_list) return; - - /* sort the list by priority */ - lang_num = 0; - count = lang_list; - while (*count && **count) { - count++; - lang_num++; - } - pl = (struct pri_list *)malloc(sizeof(struct pri_list) * lang_num); - for (i = 0; i < lang_num; i++) { - char *pri_code; - if ((pri_code=strstr(lang_list[i], ";q="))) { - *pri_code = '\0'; - pri_code += 3; - sscanf(pri_code, "%f", &(pl[i].pri)); - } else { - pl[i].pri = 1; - } - pl[i].string = strdup(lang_list[i]); - } - str_list_free(&lang_list); - - qsort(pl, lang_num, sizeof(struct pri_list), QSORT_CAST qsort_cmp_list); - - /* it's not an error to not initialise - we just fall back to - the default */ - - for (i = 0; i < lang_num; i++) { - if (lang_tdb_init(pl[i].string)) break; - } - - for (i = 0; i < lang_num; i++) { - SAFE_FREE(pl[i].string); - } - SAFE_FREE(pl); - - return; -} diff --git a/source4/web/startstop.c b/source4/web/startstop.c deleted file mode 100644 index 94578dc19e..0000000000 --- a/source4/web/startstop.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - Unix SMB/CIFS implementation. - start/stop nmbd and smbd - Copyright (C) Andrew Tridgell 1998 - - 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 "dynconfig.h" - -/** Need to wait for daemons to startup */ -#define SLEEP_TIME 3 - -/** Startup smbd from web interface. */ -void start_smbd(void) -{ - pstring binfile; - - if (geteuid() != 0) return; - - if (fork()) { - sleep(SLEEP_TIME); - return; - } - - slprintf(binfile, sizeof(pstring) - 1, "%s/smbd", dyn_SBINDIR); - - become_daemon(True); - - execl(binfile, binfile, "-D", NULL); - - exit(0); -} - -/* startup nmbd */ -void start_nmbd(void) -{ - pstring binfile; - - if (geteuid() != 0) return; - - if (fork()) { - sleep(SLEEP_TIME); - return; - } - - slprintf(binfile, sizeof(pstring) - 1, "%s/nmbd", dyn_SBINDIR); - - become_daemon(True); - - execl(binfile, binfile, "-D", NULL); - - exit(0); -} - -/** Startup winbindd from web interface. */ -void start_winbindd(void) -{ - pstring binfile; - - if (geteuid() != 0) return; - - if (fork()) { - sleep(SLEEP_TIME); - return; - } - - slprintf(binfile, sizeof(pstring) - 1, "%s/winbindd", dyn_SBINDIR); - - become_daemon(True); - - execl(binfile, binfile, NULL); - - exit(0); -} - - -/* stop smbd */ -void stop_smbd(void) -{ - pid_t pid = pidfile_pid("smbd"); - - if (geteuid() != 0) return; - - if (pid <= 0) return; - - kill(pid, SIGTERM); -} - -/* stop nmbd */ -void stop_nmbd(void) -{ - pid_t pid = pidfile_pid("nmbd"); - - if (geteuid() != 0) return; - - if (pid <= 0) return; - - kill(pid, SIGTERM); -} -#ifdef WITH_WINBIND -/* stop winbindd */ -void stop_winbindd(void) -{ - pid_t pid = pidfile_pid("winbindd"); - - if (geteuid() != 0) return; - - if (pid <= 0) return; - - kill(pid, SIGTERM); -} -#endif -/* kill a specified process */ -void kill_pid(pid_t pid) -{ - if (geteuid() != 0) return; - - if (pid <= 0) return; - - kill(pid, SIGTERM); - sleep(SLEEP_TIME); -} diff --git a/source4/web/statuspage.c b/source4/web/statuspage.c deleted file mode 100644 index c83d0af021..0000000000 --- a/source4/web/statuspage.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - Unix SMB/CIFS implementation. - web status page - Copyright (C) Andrew Tridgell 1997-1998 - - 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" - -#define PIDMAP struct PidMap - -PIDMAP { - PIDMAP *next, *prev; - pid_t pid; - char *machine; -}; - -static PIDMAP *pidmap; -static int PID_or_Machine; /* 0 = show PID, else show Machine name */ - -static pid_t smbd_pid; - -/* from 2nd call on, remove old list */ -static void initPid2Machine (void) -{ - /* show machine name rather PID on table "Open Files"? */ - if (PID_or_Machine) { - PIDMAP *p; - - for (p = pidmap; p != NULL; ) { - DLIST_REMOVE(pidmap, p); - SAFE_FREE(p->machine); - SAFE_FREE(p); - } - - pidmap = NULL; - } -} - -/* add new PID <-> Machine name mapping */ -static void addPid2Machine (pid_t pid, char *machine) -{ - /* show machine name rather PID on table "Open Files"? */ - if (PID_or_Machine) { - PIDMAP *newmap; - - if ((newmap = (PIDMAP *) malloc (sizeof (PIDMAP))) == NULL) { - /* XXX need error message for this? - if malloc fails, PID is always shown */ - return; - } - - newmap->pid = pid; - newmap->machine = strdup (machine); - - DLIST_ADD(pidmap, newmap); - } -} - -/* lookup PID <-> Machine name mapping */ -static char *mapPid2Machine (pid_t pid) -{ - static char pidbuf [64]; - PIDMAP *map; - - /* show machine name rather PID on table "Open Files"? */ - if (PID_or_Machine) { - for (map = pidmap; map != NULL; map = map->next) { - if (pid == map->pid) { - if (map->machine == NULL) /* no machine name */ - break; /* show PID */ - - return map->machine; - } - } - } - - /* PID not in list or machine name NULL? return pid as string */ - snprintf (pidbuf, sizeof (pidbuf) - 1, "%d", pid); - return pidbuf; -} - -static char *tstring(time_t t) -{ - static pstring buf; - pstrcpy(buf, asctime(localtime(&t))); - all_string_sub(buf," "," ",sizeof(buf)); - return buf; -} - -static void print_share_mode(share_mode_entry *e, char *fname) -{ - d_printf("<tr><td>%s</td>",_(mapPid2Machine(e->pid))); - d_printf("<td>"); - switch ((e->share_mode>>4)&0xF) { - case DENY_NONE: d_printf("DENY_NONE"); break; - case DENY_ALL: d_printf("DENY_ALL "); break; - case DENY_DOS: d_printf("DENY_DOS "); break; - case DENY_READ: d_printf("DENY_READ "); break; - case DENY_WRITE:d_printf("DENY_WRITE "); break; - } - d_printf("</td>"); - - d_printf("<td>"); - switch (e->share_mode&0xF) { - case 0: d_printf("RDONLY "); break; - case 1: d_printf("WRONLY "); break; - case 2: d_printf("RDWR "); break; - } - d_printf("</td>"); - - d_printf("<td>"); - if((e->op_type & - (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == - (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - d_printf("EXCLUSIVE+BATCH "); - else if (e->op_type & EXCLUSIVE_OPLOCK) - d_printf("EXCLUSIVE "); - else if (e->op_type & BATCH_OPLOCK) - d_printf("BATCH "); - else if (e->op_type & LEVEL_II_OPLOCK) - d_printf("LEVEL_II "); - else - d_printf("NONE "); - d_printf("</td>"); - - d_printf("<td>%s</td><td>%s</td></tr>\n", - fname,tstring(e->time.tv_sec)); -} - - -/* kill off any connections chosen by the user */ -static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) -{ - struct connections_data crec; - - if (dbuf.dsize != sizeof(crec)) - return 0; - - memcpy(&crec, dbuf.dptr, sizeof(crec)); - - if (crec.cnum == -1 && process_exists(crec.pid)) { - char buf[30]; - slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid); - if (cgi_variable(buf)) { - kill_pid(crec.pid); - } - } - return 0; -} - -/* traversal fn for showing machine connections */ -static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) -{ - struct connections_data crec; - - if (dbuf.dsize != sizeof(crec)) - return 0; - - memcpy(&crec, dbuf.dptr, sizeof(crec)); - - if (crec.cnum != -1 || !process_exists(crec.pid) || (crec.pid == smbd_pid)) - return 0; - - addPid2Machine (crec.pid, crec.machine); - - d_printf("<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td>\n", - (int)crec.pid, - crec.machine,crec.addr, - tstring(crec.start)); - if (geteuid() == 0) { - d_printf("<td><input type=submit value=\"X\" name=\"kill_%d\"></td>\n", - (int)crec.pid); - } - d_printf("</tr>\n"); - - return 0; -} - -/* traversal fn for showing share connections */ -static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state) -{ - struct connections_data crec; - TALLOC_CTX *mem_ctx; - - if (dbuf.dsize != sizeof(crec)) - return 0; - - memcpy(&crec, dbuf.dptr, sizeof(crec)); - - if (crec.cnum == -1 || !process_exists(crec.pid)) - return 0; - - mem_ctx = talloc_init("smbgroupedit talloc"); - if (!mem_ctx) return -1; - d_printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>\n", - crec.name,uidtoname(crec.uid), - gidtoname(mem_ctx, crec.gid),(int)crec.pid, - crec.machine, - tstring(crec.start)); - talloc_destroy(mem_ctx); - return 0; -} - - -/* show the current server status */ -void status_page(void) -{ - const char *v; - int autorefresh=0; - int refresh_interval=30; - TDB_CONTEXT *tdb; - - smbd_pid = pidfile_pid("smbd"); - - if (cgi_variable("smbd_restart")) { - stop_smbd(); - start_smbd(); - } - - if (cgi_variable("smbd_start")) { - start_smbd(); - } - - if (cgi_variable("smbd_stop")) { - stop_smbd(); - } - - if (cgi_variable("nmbd_restart")) { - stop_nmbd(); - start_nmbd(); - } - if (cgi_variable("nmbd_start")) { - start_nmbd(); - } - - if (cgi_variable("nmbd_stop")) { - stop_nmbd(); - } - -#ifdef WITH_WINBIND - if (cgi_variable("winbindd_restart")) { - stop_winbindd(); - start_winbindd(); - } - - if (cgi_variable("winbindd_start")) { - start_winbindd(); - } - - if (cgi_variable("winbindd_stop")) { - stop_winbindd(); - } -#endif - if (cgi_variable("autorefresh")) { - autorefresh = 1; - } else if (cgi_variable("norefresh")) { - autorefresh = 0; - } else if (cgi_variable("refresh")) { - autorefresh = 1; - } - - if ((v=cgi_variable("refresh_interval"))) { - refresh_interval = atoi(v); - } - - if (cgi_variable("show_client_in_col_1")) { - PID_or_Machine = 1; - } - - tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); - if (tdb) tdb_traverse(tdb, traverse_fn1, NULL); - - initPid2Machine (); - - d_printf("<H2>%s</H2>\n", _("Server Status")); - - d_printf("<FORM method=post>\n"); - - if (!autorefresh) { - d_printf("<input type=submit value=\"%s\" name=autorefresh>\n", _("Auto Refresh")); - d_printf("<br>%s", _("Refresh Interval: ")); - d_printf("<input type=text size=2 name=\"refresh_interval\" value=%d>\n", - refresh_interval); - } else { - d_printf("<input type=submit value=\"%s\" name=norefresh>\n", _("Stop Refreshing")); - d_printf("<br>%s%d\n", _("Refresh Interval: "), refresh_interval); - d_printf("<input type=hidden name=refresh value=1>\n"); - } - - d_printf("<p>\n"); - - if (!tdb) { - /* open failure either means no connections have been - made */ - } - - - d_printf("<table>\n"); - - d_printf("<tr><td>%s</td><td>%s</td></tr>", _("version:"), VERSION); - - fflush(stdout); - d_printf("<tr><td>%s</td><td>%s</td>\n", _("smbd:"), smbd_running()?_("running"):_("not running")); - if (geteuid() == 0) { - if (smbd_running()) { - d_printf("<td><input type=submit name=\"smbd_stop\" value=\"%s\"></td>\n", _("Stop smbd")); - } else { - d_printf("<td><input type=submit name=\"smbd_start\" value=\"%s\"></td>\n", _("Start smbd")); - } - d_printf("<td><input type=submit name=\"smbd_restart\" value=\"%s\"></td>\n", _("Restart smbd")); - } - d_printf("</tr>\n"); - - fflush(stdout); - d_printf("<tr><td>%s</td><td>%s</td>\n", _("nmbd:"), nmbd_running()?_("running"):_("not running")); - if (geteuid() == 0) { - if (nmbd_running()) { - d_printf("<td><input type=submit name=\"nmbd_stop\" value=\"%s\"></td>\n", _("Stop nmbd")); - } else { - d_printf("<td><input type=submit name=\"nmbd_start\" value=\"%s\"></td>\n", _("Start nmbd")); - } - d_printf("<td><input type=submit name=\"nmbd_restart\" value=\"%s\"></td>\n", _("Restart nmbd")); - } - d_printf("</tr>\n"); - -#ifdef WITH_WINBIND - fflush(stdout); - d_printf("<tr><td>%s</td><td>%s</td>\n", _("winbindd:"), winbindd_running()?_("running"):_("not running")); - if (geteuid() == 0) { - if (winbindd_running()) { - d_printf("<td><input type=submit name=\"winbindd_stop\" value=\"%s\"></td>\n", _("Stop winbindd")); - } else { - d_printf("<td><input type=submit name=\"winbindd_start\" value=\"%s\"></td>\n", _("Start winbindd")); - } - d_printf("<td><input type=submit name=\"winbindd_restart\" value=\"%s\"></td>\n", _("Restart winbindd")); - } - d_printf("</tr>\n"); -#endif - - d_printf("</table>\n"); - fflush(stdout); - - d_printf("<p><h3>%s</h3>\n", _("Active Connections")); - d_printf("<table border=1>\n"); - d_printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th>\n", _("PID"), _("Client"), _("IP address"), _("Date")); - if (geteuid() == 0) { - d_printf("<th>%s</th>\n", _("Kill")); - } - d_printf("</tr>\n"); - - if (tdb) tdb_traverse(tdb, traverse_fn2, NULL); - - d_printf("</table><p>\n"); - - d_printf("<p><h3>%s</h3>\n", _("Active Shares")); - d_printf("<table border=1>\n"); - d_printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n\n", - _("Share"), _("User"), _("Group"), _("PID"), _("Client"), _("Date")); - - if (tdb) tdb_traverse(tdb, traverse_fn3, NULL); - - d_printf("</table><p>\n"); - - d_printf("<h3>%s</h3>\n", _("Open Files")); - d_printf("<table border=1>\n"); - d_printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n", _("PID"), _("Sharing"), _("R/W"), _("Oplock"), _("File"), _("Date")); - - locking_init(1); - share_mode_forall(print_share_mode); - locking_end(); - d_printf("</table>\n"); - - if (tdb) tdb_close(tdb); - - d_printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"Show Client in col 1\">\n"); - d_printf("<input type=submit name=\"show_pid_in_col_1\" value=\"Show PID in col 1\">\n"); - - d_printf("</FORM>\n"); - - if (autorefresh) { - /* this little JavaScript allows for automatic refresh - of the page. There are other methods but this seems - to be the best alternative */ - d_printf("<script language=\"JavaScript\">\n"); - d_printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n", - cgi_baseurl(), - refresh_interval, - refresh_interval*1000); - d_printf("//-->\n</script>\n"); - } -} diff --git a/source4/web/swat.c b/source4/web/swat.c deleted file mode 100644 index ec646f5848..0000000000 --- a/source4/web/swat.c +++ /dev/null @@ -1,1343 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba Web Administration Tool - Version 3.0.0 - Copyright (C) Andrew Tridgell 1997-2002 - Copyright (C) John H Terpstra 2002 - - 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. -*/ - -/** - * @defgroup swat SWAT - Samba Web Administration Tool - * @{ - * @file swat.c - * - * @brief Samba Web Administration Tool. - **/ - -#include "includes.h" - -#define GLOBALS_SNUM -1 - -static BOOL demo_mode = False; -static BOOL have_write_access = False; -static BOOL have_read_access = False; -static int iNumNonAutoPrintServices = 0; - -/* - * Password Management Globals - */ -#define SWAT_USER "username" -#define OLD_PSWD "old_passwd" -#define NEW_PSWD "new_passwd" -#define NEW2_PSWD "new2_passwd" -#define CHG_S_PASSWD_FLAG "chg_s_passwd_flag" -#define CHG_R_PASSWD_FLAG "chg_r_passwd_flag" -#define ADD_USER_FLAG "add_user_flag" -#define DELETE_USER_FLAG "delete_user_flag" -#define DISABLE_USER_FLAG "disable_user_flag" -#define ENABLE_USER_FLAG "enable_user_flag" -#define RHOST "remote_host" - -/* we need these because we link to locking*.o */ - void become_root(void) {} - void unbecome_root(void) {} - -/**************************************************************************** -****************************************************************************/ -static int enum_index(int value, const struct enum_list *enumlist) -{ - int i; - for (i=0;enumlist[i].name;i++) - if (value == enumlist[i].value) break; - return(i); -} - -static char *fix_backslash(const char *str) -{ - static char newstring[1024]; - char *p = newstring; - - while (*str) { - if (*str == '\\') {*p++ = '\\';*p++ = '\\';} - else *p++ = *str; - ++str; - } - *p = '\0'; - return newstring; -} - -static char *stripspaceupper(const char *str) -{ - static char newstring[1024]; - char *p = newstring; - - while (*str) { - if (*str != ' ') *p++ = toupper(*str); - ++str; - } - *p = '\0'; - return newstring; -} - -static char *make_parm_name(const char *label) -{ - static char parmname[1024]; - char *p = parmname; - - while (*label) { - if (*label == ' ') *p++ = '_'; - else *p++ = *label; - ++label; - } - *p = '\0'; - return parmname; -} - -/**************************************************************************** - include a lump of html in a page -****************************************************************************/ -static int include_html(const char *fname) -{ - int fd; - char buf[1024]; - int ret; - - fd = web_open(fname, O_RDONLY, 0); - - if (fd == -1) { - d_printf("ERROR: Can't open %s\n", fname); - return 0; - } - - while ((ret = read(fd, buf, sizeof(buf))) > 0) { - write(1, buf, ret); - } - - close(fd); - return 1; -} - -/**************************************************************************** - start the page with standard stuff -****************************************************************************/ -static void print_header(void) -{ - if (!cgi_waspost()) { - d_printf("Expires: 0\r\n"); - } - d_printf("Content-type: text/html\r\n\r\n"); - - if (!include_html("include/header.html")) { - d_printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"); - d_printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n"); - } -} - -/* ******************************************************************* - show parameter label with translated name in the following form - because showing original and translated label in one line looks - too long, and showing translated label only is unusable for - heavy users. - ------------------------------- - HELP security [combo box][button] - SECURITY - ------------------------------- - (capital words are translated by gettext.) - if no translation is available, then same form as original is - used. - "i18n_translated_parm" class is used to change the color of the - translated parameter with CSS. - **************************************************************** */ -static const char* get_parm_translated( - const char* pAnchor, const char* pHelp, const char* pLabel) -{ - const char* pTranslated = _(pLabel); - static pstring output; - if(strcmp(pLabel, pTranslated) != 0) - { - snprintf(output, sizeof(output), - "<A HREF=\"/swat/help/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>", - pAnchor, pHelp, pLabel, pTranslated); - return output; - } - snprintf(output, sizeof(output), - "<A HREF=\"/swat/help/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s", - pAnchor, pHelp, pLabel); - return output; -} -/**************************************************************************** - finish off the page -****************************************************************************/ -static void print_footer(void) -{ - if (!include_html("include/footer.html")) { - d_printf("\n</BODY>\n</HTML>\n"); - } -} - -/**************************************************************************** - display one editable parameter in a form -****************************************************************************/ -static void show_parameter(int snum, struct parm_struct *parm) -{ - int i; - void *ptr = parm->ptr; - - if (parm->class == P_LOCAL && snum >= 0) { - ptr = lp_local_ptr(snum, ptr); - } - - printf("<tr><td>%s</td><td>", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label)); - switch (parm->type) { - case P_CHAR: - d_printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">", - make_parm_name(parm->label), *(char *)ptr); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">", - _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue)); - break; - - case P_LIST: - d_printf("<input type=text size=40 name=\"parm_%s\" value=\"", - make_parm_name(parm->label)); - if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) { - char **list = *(char ***)ptr; - for (;*list;list++) { - d_printf("%s%s", *list, ((*(list+1))?" ":"")); - } - } - d_printf("\">"); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'", - _("Set Default"), make_parm_name(parm->label)); - if (parm->def.lvalue) { - char **list = (char **)(parm->def.lvalue); - for (; *list; list++) { - d_printf("%s%s", *list, ((*(list+1))?" ":"")); - } - } - d_printf("\'\">"); - break; - - case P_STRING: - case P_USTRING: - d_printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">", - make_parm_name(parm->label), *(char **)ptr); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">", - _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue))); - break; - - case P_BOOL: - d_printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); - d_printf("<option %s>Yes", (*(BOOL *)ptr)?"selected":""); - d_printf("<option %s>No", (*(BOOL *)ptr)?"":"selected"); - d_printf("</select>"); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">", - _("Set Default"), make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?0:1); - break; - - case P_BOOLREV: - d_printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); - d_printf("<option %s>Yes", (*(BOOL *)ptr)?"":"selected"); - d_printf("<option %s>No", (*(BOOL *)ptr)?"selected":""); - d_printf("</select>"); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">", - _("Set Default"), make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?1:0); - break; - - case P_INTEGER: - d_printf("<input type=text size=8 name=\"parm_%s\" value=%d>", make_parm_name(parm->label), *(int *)ptr); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">", - _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue)); - break; - - case P_OCTAL: - d_printf("<input type=text size=8 name=\"parm_%s\" value=%s>", make_parm_name(parm->label), octal_string(*(int *)ptr)); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">", - _("Set Default"), make_parm_name(parm->label), - octal_string((int)(parm->def.ivalue))); - break; - - case P_ENUM: - d_printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); - for (i=0;parm->enum_list[i].name;i++) { - if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) { - d_printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name); - } - } - d_printf("</select>"); - d_printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">", - _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list)); - break; - case P_SEP: - break; - } - d_printf("</td></tr>\n"); -} - -/**************************************************************************** - display a set of parameters for a service -****************************************************************************/ -static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers) -{ - int i = 0; - struct parm_struct *parm; - const char *heading = NULL; - const char *last_heading = NULL; - - while ((parm = lp_next_parameter(snum, &i, allparameters))) { - if (snum < 0 && parm->class == P_LOCAL && !(parm->flags & FLAG_GLOBAL)) - continue; - if (parm->class == P_SEPARATOR) { - heading = parm->label; - continue; - } - if (parm->flags & FLAG_HIDE) continue; - if (snum >= 0) { - if (printers & !(parm->flags & FLAG_PRINT)) continue; - if (!printers & !(parm->flags & FLAG_SHARE)) continue; - } - if (parm_filter == FLAG_BASIC) { - if (!(parm->flags & FLAG_BASIC)) { - void *ptr = parm->ptr; - - if (parm->class == P_LOCAL && snum >= 0) { - ptr = lp_local_ptr(snum, ptr); - } - - switch (parm->type) { - case P_CHAR: - if (*(char *)ptr == (char)(parm->def.cvalue)) continue; - break; - - case P_LIST: - if (!str_list_compare(*(char ***)ptr, (char **)(parm->def.lvalue))) continue; - break; - - case P_STRING: - case P_USTRING: - if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue; - break; - - case P_BOOL: - case P_BOOLREV: - if (*(BOOL *)ptr == (BOOL)(parm->def.bvalue)) continue; - break; - - case P_INTEGER: - case P_OCTAL: - if (*(int *)ptr == (int)(parm->def.ivalue)) continue; - break; - - - case P_ENUM: - if (*(int *)ptr == (int)(parm->def.ivalue)) continue; - break; - case P_SEP: - continue; - } - } - if (printers && !(parm->flags & FLAG_PRINT)) continue; - } - if (parm_filter == FLAG_WIZARD) { - if (!((parm->flags & FLAG_WIZARD))) continue; - } - if (parm_filter == FLAG_ADVANCED) { - if (!((parm->flags & FLAG_ADVANCED))) continue; - } - if (heading && heading != last_heading) { - d_printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading)); - last_heading = heading; - } - show_parameter(snum, parm); - } -} - -/**************************************************************************** - load the smb.conf file into loadparm. -****************************************************************************/ -static BOOL load_config(BOOL save_def) -{ - lp_resetnumservices(); - return lp_load(dyn_CONFIGFILE,False,save_def,False); -} - -/**************************************************************************** - write a config file -****************************************************************************/ -static void write_config(FILE *f, BOOL show_defaults) -{ - fprintf(f, "# Samba config file created using SWAT\n"); - fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr()); - fprintf(f, "# Date: %s\n\n", timestring(time(NULL))); - - lp_dump(f, show_defaults, iNumNonAutoPrintServices); -} - -/**************************************************************************** - save and reload the smb.conf config file -****************************************************************************/ -static int save_reload(int snum) -{ - FILE *f; - struct stat st; - - f = sys_fopen(dyn_CONFIGFILE,"w"); - if (!f) { - d_printf("failed to open %s for writing\n", dyn_CONFIGFILE); - return 0; - } - - /* just in case they have used the buggy xinetd to create the file */ - if (fstat(fileno(f), &st) == 0 && - (st.st_mode & S_IWOTH)) { - fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); - } - - write_config(f, False); - if (snum) - lp_dump_one(f, False, snum); - fclose(f); - - lp_killunused(NULL); - - if (!load_config(False)) { - d_printf("Can't reload %s\n", dyn_CONFIGFILE); - return 0; - } - iNumNonAutoPrintServices = lp_numservices(); - load_printers(); - - return 1; -} - -/**************************************************************************** - commit one parameter -****************************************************************************/ -static void commit_parameter(int snum, struct parm_struct *parm, const char *v) -{ - int i; - char *s; - - if (snum < 0 && parm->class == P_LOCAL) { - /* this handles the case where we are changing a local - variable globally. We need to change the parameter in - all shares where it is currently set to the default */ - for (i=0;i<lp_numservices();i++) { - s = lp_servicename(i); - if (s && (*s) && lp_is_default(i, parm)) { - lp_do_parameter(i, parm->label, v); - } - } - } - - lp_do_parameter(snum, parm->label, v); -} - -/**************************************************************************** - commit a set of parameters for a service -****************************************************************************/ -static void commit_parameters(int snum) -{ - int i = 0; - struct parm_struct *parm; - pstring label; - const char *v; - - while ((parm = lp_next_parameter(snum, &i, 1))) { - slprintf(label, sizeof(label)-1, "parm_%s", make_parm_name(parm->label)); - if ((v = cgi_variable(label))) { - if (parm->flags & FLAG_HIDE) continue; - commit_parameter(snum, parm, v); - } - } -} - -/**************************************************************************** - spit out the html for a link with an image -****************************************************************************/ -static void image_link(const char *name, const char *hlink, const char *src) -{ - d_printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", - cgi_baseurl(), hlink, src, name); -} - -/**************************************************************************** - display the main navigation controls at the top of each page along - with a title -****************************************************************************/ -static void show_main_buttons(void) -{ - char *p; - - if ((p = cgi_user_name()) && strcmp(p, "root")) { - d_printf(_("Logged in as <b>%s</b><p>\n"), p); - } - - image_link(_("Home"), "", "images/home.gif"); - if (have_write_access) { - image_link(_("Globals"), "globals", "images/globals.gif"); - image_link(_("Shares"), "shares", "images/shares.gif"); - image_link(_("Printers"), "printers", "images/printers.gif"); - image_link(_("Wizard"), "wizard", "images/wizard.gif"); - } - if (have_read_access) { - image_link(_("Status"), "status", "images/status.gif"); - image_link(_("View Config"), "viewconfig", "images/viewconfig.gif"); - } - image_link(_("Password Management"), "passwd", "images/passwd.gif"); - - d_printf("<HR>\n"); -} - -/**************************************************************************** - * Handle Display/Edit Mode CGI - ****************************************************************************/ -static void ViewModeBoxes(int mode) -{ - d_printf("<p>%s\n", _("Configuration View: ")); - d_printf("<input type=radio name=\"ViewMode\" value=0 %s>Basic\n", (mode == 0) ? "checked" : ""); - d_printf("<input type=radio name=\"ViewMode\" value=1 %s>Advanced\n", (mode == 1) ? "checked" : ""); - d_printf("<input type=radio name=\"ViewMode\" value=2 %s>Developer\n", (mode == 2) ? "checked" : ""); - d_printf("</p><br>\n"); -} - -/**************************************************************************** - display a welcome page -****************************************************************************/ -static void welcome_page(void) -{ - include_html("help/welcome.html"); -} - -/**************************************************************************** - display the current smb.conf -****************************************************************************/ -static void viewconfig_page(void) -{ - int full_view=0; - - if (cgi_variable("full_view")) { - full_view = 1; - } - - d_printf("<H2>%s</H2>\n", _("Current Config")); - d_printf("<form method=post>\n"); - - if (full_view) { - d_printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View")); - } else { - d_printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View")); - } - - d_printf("<p><pre>"); - write_config(stdout, full_view); - d_printf("</pre>"); - d_printf("</form>\n"); -} - -/**************************************************************************** - second screen of the wizard ... Fetch Configuration Parameters -****************************************************************************/ -static void wizard_params_page(void) -{ - unsigned int parm_filter = FLAG_WIZARD; - - /* Here we first set and commit all the parameters that were selected - in the previous screen. */ - - d_printf("<H2>Wizard Parameter Edit Page</H2>\n"); - - if (cgi_variable("Commit")) { - commit_parameters(GLOBALS_SNUM); - save_reload(0); - } - - d_printf("<form name=\"swatform\" method=post action=wizard_params>\n"); - - if (have_write_access) { - d_printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n"); - } - - d_printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n"); - d_printf("<p>\n"); - - d_printf("<table>\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); - d_printf("</table>\n"); - d_printf("</form>\n"); -} - -/**************************************************************************** - Utility to just rewrite the smb.conf file - effectively just cleans it up -****************************************************************************/ -static void rewritecfg_file(void) -{ - commit_parameters(GLOBALS_SNUM); - save_reload(0); - d_printf("<H2>Note: smb.conf %s</H2>\n", _("file has been read and rewritten")); -} - -/**************************************************************************** - wizard to create/modify the smb.conf file -****************************************************************************/ -static void wizard_page(void) -{ - /* Set some variables to collect data from smb.conf */ - int role = 0; - int winstype = 0; - int have_home = -1; - int HomeExpo = 0; - int SerType = 0; - - if (cgi_variable("Rewrite")) { - (void) rewritecfg_file(); - return; - } - - if (cgi_variable("GetWizardParams")){ - (void) wizard_params_page(); - return; - } - - if (cgi_variable("Commit")){ - SerType = atoi(cgi_variable("ServerType")); - winstype = atoi(cgi_variable("WINSType")); - have_home = lp_servicenumber(HOMES_NAME); - HomeExpo = atoi(cgi_variable("HomeExpo")); - - /* Plain text passwords are too badly broken - use encrypted passwords only */ - lp_do_parameter( GLOBALS_SNUM, "encrypt passwords", "Yes"); - - switch ( SerType ){ - case 0: - /* Stand-alone Server */ - lp_do_parameter( GLOBALS_SNUM, "security", "USER" ); - lp_do_parameter( GLOBALS_SNUM, "domain logons", "No" ); - break; - case 1: - /* Domain Member */ - lp_do_parameter( GLOBALS_SNUM, "security", "DOMAIN" ); - lp_do_parameter( GLOBALS_SNUM, "domain logons", "No" ); - break; - case 2: - /* Domain Controller */ - lp_do_parameter( GLOBALS_SNUM, "security", "USER" ); - lp_do_parameter( GLOBALS_SNUM, "domain logons", "Yes" ); - break; - } - switch ( winstype ) { - case 0: - lp_do_parameter( GLOBALS_SNUM, "wins support", "No" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", "" ); - break; - case 1: - lp_do_parameter( GLOBALS_SNUM, "wins support", "Yes" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", "" ); - break; - case 2: - lp_do_parameter( GLOBALS_SNUM, "wins support", "No" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", cgi_variable("WINSAddr")); - break; - } - - /* Have to create Homes share? */ - if ((HomeExpo == 1) && (have_home == -1)) { - pstring unix_share; - - pstrcpy(unix_share,HOMES_NAME); - load_config(False); - lp_copy_service(GLOBALS_SNUM, unix_share); - iNumNonAutoPrintServices = lp_numservices(); - have_home = lp_servicenumber(HOMES_NAME); - lp_do_parameter( have_home, "read only", "No"); - lp_do_parameter( have_home, "valid users", "%S"); - lp_do_parameter( have_home, "browseable", "No"); - commit_parameters(have_home); - } - - /* Need to Delete Homes share? */ - if ((HomeExpo == 0) && (have_home != -1)) { - lp_remove_service(have_home); - have_home = -1; - } - - commit_parameters(GLOBALS_SNUM); - save_reload(0); - } - else - { - /* Now determine smb.conf WINS settings */ - if (lp_wins_support()) - winstype = 1; - if (lp_wins_server_list() && strlen(*lp_wins_server_list())) - winstype = 2; - - - /* Do we have a homes share? */ - have_home = lp_servicenumber(HOMES_NAME); - } - if ((winstype == 2) && lp_wins_support()) - winstype = 3; - - role = lp_server_role(); - - /* Here we go ... */ - d_printf("<H2>Samba Configuration Wizard</H2>\n"); - d_printf("<form method=post action=wizard>\n"); - - if (have_write_access) { - d_printf(_("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments.\n")); - d_printf(_("The same will happen if you press the commit button.")); - d_printf("<br><br>"); - d_printf("<center>"); - d_printf("<input type=submit name=\"Rewrite\" value=%s> ",_("Rewrite smb.conf file")); - d_printf("<input type=submit name=\"Commit\" value=%s> ",_("Commit")); - d_printf("<input type=submit name=\"GetWizardParams\" value=%s>", _("Edit Parameter Values")); - d_printf("</center>"); - } - - d_printf("<hr>"); - d_printf("<center><table border=0>"); - d_printf("<tr><td><b>%s</b></td>\n", "Server Type: "); - d_printf("<td><input type=radio name=\"ServerType\" value=0 %s> Stand Alone </td>", (role == ROLE_STANDALONE) ? "checked" : ""); - d_printf("<td><input type=radio name=\"ServerType\" value=1 %s> Domain Member </td>", (role == ROLE_DOMAIN_MEMBER) ? "checked" : ""); - d_printf("<td><input type=radio name=\"ServerType\" value=2 %s> Domain Controller </td>", (role == ROLE_DOMAIN_PDC) ? "checked" : ""); - d_printf("</tr>"); - if (role == ROLE_DOMAIN_BDC) { - d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Unusual Type in smb.conf - Please Select New Mode</font></td></tr>"); - } - d_printf("<tr><td><b>%s</b></td>\n", "Configure WINS As: "); - d_printf("<td><input type=radio name=\"WINSType\" value=0 %s> Not Used </td>", (winstype == 0) ? "checked" : ""); - d_printf("<td><input type=radio name=\"WINSType\" value=1 %s> Server for client use </td>", (winstype == 1) ? "checked" : ""); - d_printf("<td><input type=radio name=\"WINSType\" value=2 %s> Client of another WINS server </td>", (winstype == 2) ? "checked" : ""); - d_printf("<tr><td></td><td></td><td></td><td>Remote WINS Server <input type=text size=\"16\" name=\"WINSAddr\" value=\"%s\"></td></tr>",lp_wins_server_list()); - if (winstype == 3) { - d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Error: WINS Server Mode and WINS Support both set in smb.conf</font></td></tr>"); - d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Please Select desired WINS mode above.</font></td></tr>"); - } - d_printf("</tr>"); - d_printf("<tr><td><b>%s</b></td>\n","Expose Home Directories: "); - d_printf("<td><input type=radio name=\"HomeExpo\" value=1 %s> Yes</td>", (have_home == -1) ? "" : "checked "); - d_printf("<td><input type=radio name=\"HomeExpo\" value=0 %s> No</td>", (have_home == -1 ) ? "checked" : ""); - d_printf("<td></td></tr>"); - - /* Enable this when we are ready .... - * d_printf("<tr><td><b>%s</b></td>\n","Is Print Server: "); - * d_printf("<td><input type=radio name=\"PtrSvr\" value=1 %s> Yes</td>"); - * d_printf("<td><input type=radio name=\"PtrSvr\" value=0 %s> No</td>"); - * d_printf("<td></td></tr>"); - */ - - d_printf("</table></center>"); - d_printf("<hr>"); - - d_printf(_("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment.\n")); - d_printf("</form>\n"); -} - - -/**************************************************************************** - display a globals editing page -****************************************************************************/ -static void globals_page(void) -{ - unsigned int parm_filter = FLAG_BASIC; - int mode = 0; - - d_printf("<H2>%s</H2>\n", _("Global Variables")); - - if (cgi_variable("Commit")) { - commit_parameters(GLOBALS_SNUM); - save_reload(0); - } - - if ( cgi_variable("ViewMode") ) - mode = atoi(cgi_variable("ViewMode")); - - d_printf("<form name=\"swatform\" method=post action=globals>\n"); - - ViewModeBoxes( mode ); - switch ( mode ) { - case 0: - parm_filter = FLAG_BASIC; - break; - case 1: - parm_filter = FLAG_ADVANCED; - break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; - } - d_printf("<br>\n"); - if (have_write_access) { - d_printf("<input type=submit name=\"Commit\" value=\"%s\">\n", - _("Commit Changes")); - } - - d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", - _("Reset Values")); - - d_printf("<p>\n"); - d_printf("<table>\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); - d_printf("</table>\n"); - d_printf("</form>\n"); -} - -/**************************************************************************** - display a shares editing page. share is in unix codepage, and must be in - dos codepage. FIXME !!! JRA. -****************************************************************************/ -static void shares_page(void) -{ - const char *share = cgi_variable("share"); - char *s; - int snum = -1; - int i; - int mode = 0; - unsigned int parm_filter = FLAG_BASIC; - - if (share) - snum = lp_servicenumber(share); - - d_printf("<H2>%s</H2>\n", _("Share Parameters")); - - if (cgi_variable("Commit") && snum >= 0) { - commit_parameters(snum); - save_reload(0); - } - - if (cgi_variable("Delete") && snum >= 0) { - lp_remove_service(snum); - save_reload(0); - share = NULL; - snum = -1; - } - - if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) { - load_config(False); - lp_copy_service(GLOBALS_SNUM, share); - iNumNonAutoPrintServices = lp_numservices(); - save_reload(0); - snum = lp_servicenumber(share); - } - - d_printf("<FORM name=\"swatform\" method=post>\n"); - - d_printf("<table>\n"); - if ( cgi_variable("ViewMode") ) - mode = atoi(cgi_variable("ViewMode")); - ViewModeBoxes( mode ); - switch ( mode ) { - case 0: - parm_filter = FLAG_BASIC; - break; - case 1: - parm_filter = FLAG_ADVANCED; - break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; - } - d_printf("<br><tr>\n"); - d_printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share")); - d_printf("<td><select name=share>\n"); - if (snum < 0) - d_printf("<option value=\" \"> \n"); - for (i=0;i<lp_numservices();i++) { - s = lp_servicename(i); - if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) { - d_printf("<option %s value=\"%s\">%s\n", - (share && strcmp(share,s)==0)?"SELECTED":"", - s, s); - } - } - d_printf("</select></td>\n"); - if (have_write_access) { - d_printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share")); - } - d_printf("</tr>\n"); - d_printf("</table>"); - d_printf("<table>"); - if (have_write_access) { - d_printf("<tr>\n"); - d_printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share")); - d_printf("<td><input type=text size=30 name=newshare></td></tr>\n"); - } - d_printf("</table>"); - - - if (snum >= 0) { - if (have_write_access) { - d_printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes")); - } - - d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values")); - d_printf("<p>\n"); - } - - if (snum >= 0) { - d_printf("<table>\n"); - show_parameters(snum, 1, parm_filter, 0); - d_printf("</table>\n"); - } - - d_printf("</FORM>\n"); -} - -/************************************************************* -change a password either locally or remotely -*************************************************************/ -static BOOL change_password(const char *remote_machine, const char *user_name, - const char *old_passwd, const char *new_passwd, - int local_flags) -{ - BOOL ret = False; - pstring err_str; - pstring msg_str; - - if (demo_mode) { - d_printf("%s<p>", _("password change in demo mode rejected\n")); - return False; - } - - if (remote_machine != NULL) { - ret = remote_password_change(remote_machine, user_name, old_passwd, - new_passwd, err_str, sizeof(err_str)); - if(*err_str) - d_printf("%s\n<p>", err_str); - return ret; - } - - if(!initialize_password_db(True)) { - d_printf("Can't setup password database vectors.\n<p>"); - return False; - } - - ret = local_password_change(user_name, local_flags, new_passwd, err_str, sizeof(err_str), - msg_str, sizeof(msg_str)); - - if(*msg_str) - d_printf("%s\n<p>", msg_str); - if(*err_str) - d_printf("%s\n<p>", err_str); - - return ret; -} - -/**************************************************************************** - do the stuff required to add or change a password -****************************************************************************/ -static void chg_passwd(void) -{ - const char *host; - BOOL rslt; - int local_flags = 0; - - /* Make sure users name has been specified */ - if (strlen(cgi_variable(SWAT_USER)) == 0) { - d_printf("<p>%s", _(" Must specify \"User Name\" \n")); - return; - } - - /* - * smbpasswd doesn't require anything but the users name to delete, disable or enable the user, - * so if that's what we're doing, skip the rest of the checks - */ - if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) { - - /* - * If current user is not root, make sure old password has been specified - * If REMOTE change, even root must provide old password - */ - if (((!am_root()) && (strlen( cgi_variable(OLD_PSWD)) <= 0)) || - ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable(OLD_PSWD)) <= 0))) { - d_printf("<p>%s", _(" Must specify \"Old Password\" \n")); - return; - } - - /* If changing a users password on a remote hosts we have to know what host */ - if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable(RHOST)) <= 0)) { - d_printf("<p>%s", _(" Must specify \"Remote Machine\" \n")); - return; - } - - /* Make sure new passwords have been specified */ - if ((strlen( cgi_variable(NEW_PSWD)) <= 0) || - (strlen( cgi_variable(NEW2_PSWD)) <= 0)) { - d_printf("<p>%s", _(" Must specify \"New, and Re-typed Passwords\" \n")); - return; - } - - /* Make sure new passwords was typed correctly twice */ - if (strcmp(cgi_variable(NEW_PSWD), cgi_variable(NEW2_PSWD)) != 0) { - d_printf("<p>%s", _(" Re-typed password didn't match new password\n")); - return; - } - } - - if (cgi_variable(CHG_R_PASSWD_FLAG)) { - host = cgi_variable(RHOST); - } else if (am_root()) { - host = NULL; - } else { - host = "127.0.0.1"; - } - - /* - * Set up the local flags. - */ - - local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0); - local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0); - local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0); - local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0); - - rslt = change_password(host, - cgi_variable(SWAT_USER), - cgi_variable(OLD_PSWD), cgi_variable(NEW_PSWD), - local_flags); - - if(local_flags == 0) { - d_printf("<p>"); - if (rslt == True) { - d_printf(_(" The passwd for '%s' has been changed. \n"), cgi_variable(SWAT_USER)); - } else { - d_printf(_(" The passwd for '%s' has NOT been changed. \n"), cgi_variable(SWAT_USER)); - } - } - - return; -} - -/**************************************************************************** - display a password editing page -****************************************************************************/ -static void passwd_page(void) -{ - const char *new_name = cgi_user_name(); - - /* - * After the first time through here be nice. If the user - * changed the User box text to another users name, remember it. - */ - if (cgi_variable(SWAT_USER)) { - new_name = cgi_variable(SWAT_USER); - } - - if (!new_name) new_name = ""; - - d_printf("<H2>%s</H2>\n", _("Server Password Management")); - - d_printf("<FORM name=\"swatform\" method=post>\n"); - - d_printf("<table>\n"); - - /* - * Create all the dialog boxes for data collection - */ - d_printf("<tr><td>%s</td>\n", _(" User Name : ")); - d_printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name); - if (!am_root()) { - d_printf("<tr><td>%s</td>\n", _(" Old Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD); - } - d_printf("<tr><td>%s</td>\n", _(" New Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD); - d_printf("<tr><td>%s</td>\n", _(" Re-type New Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD); - d_printf("</table>\n"); - - /* - * Create all the control buttons for requesting action - */ - d_printf("<input type=submit name=%s value=\"%s\">\n", - CHG_S_PASSWD_FLAG, _("Change Password")); - if (demo_mode || am_root()) { - d_printf("<input type=submit name=%s value=\"%s\">\n", - ADD_USER_FLAG, _("Add New User")); - d_printf("<input type=submit name=%s value=\"%s\">\n", - DELETE_USER_FLAG, _("Delete User")); - d_printf("<input type=submit name=%s value=\"%s\">\n", - DISABLE_USER_FLAG, _("Disable User")); - d_printf("<input type=submit name=%s value=\"%s\">\n", - ENABLE_USER_FLAG, _("Enable User")); - } - d_printf("<p></FORM>\n"); - - /* - * Do some work if change, add, disable or enable was - * requested. It could be this is the first time through this - * code, so there isn't anything to do. */ - if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) || - (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) { - chg_passwd(); - } - - d_printf("<H2>%s</H2>\n", _("Client/Server Password Management")); - - d_printf("<FORM name=\"swatform\" method=post>\n"); - - d_printf("<table>\n"); - - /* - * Create all the dialog boxes for data collection - */ - d_printf("<tr><td>%s</td>\n", _(" User Name : ")); - d_printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name); - d_printf("<tr><td>%s</td>\n", _(" Old Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD); - d_printf("<tr><td>%s</td>\n", _(" New Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD); - d_printf("<tr><td>%s</td>\n", _(" Re-type New Password : ")); - d_printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD); - d_printf("<tr><td>%s</td>\n", _(" Remote Machine : ")); - d_printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST); - - d_printf("</table>"); - - /* - * Create all the control buttons for requesting action - */ - d_printf("<input type=submit name=%s value=\"%s\">", - CHG_R_PASSWD_FLAG, _("Change Password")); - - d_printf("<p></FORM>\n"); - - /* - * Do some work if a request has been made to change the - * password somewhere other than the server. It could be this - * is the first time through this code, so there isn't - * anything to do. */ - if (cgi_variable(CHG_R_PASSWD_FLAG)) { - chg_passwd(); - } - -} - -/**************************************************************************** - display a printers editing page -****************************************************************************/ -static void printers_page(void) -{ - const char *share = cgi_variable("share"); - char *s; - int snum=-1; - int i; - int mode = 0; - unsigned int parm_filter = FLAG_BASIC; - - if (share) - snum = lp_servicenumber(share); - - d_printf("<H2>%s</H2>\n", _("Printer Parameters")); - - d_printf("<H3>%s</H3>\n", _("Important Note:")); - d_printf(_("Printer names marked with [*] in the Choose Printer drop-down box ")); - d_printf(_("are autoloaded printers from ")); - d_printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name")); - d_printf(_("Attempting to delete these printers from SWAT will have no effect.\n")); - - if (cgi_variable("Commit") && snum >= 0) { - commit_parameters(snum); - if (snum >= iNumNonAutoPrintServices) - save_reload(snum); - else - save_reload(0); - } - - if (cgi_variable("Delete") && snum >= 0) { - lp_remove_service(snum); - save_reload(0); - share = NULL; - snum = -1; - } - - if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) { - load_config(False); - lp_copy_service(GLOBALS_SNUM, share); - iNumNonAutoPrintServices = lp_numservices(); - snum = lp_servicenumber(share); - lp_do_parameter(snum, "print ok", "Yes"); - save_reload(0); - snum = lp_servicenumber(share); - } - - d_printf("<FORM name=\"swatform\" method=post>\n"); - - if ( cgi_variable("ViewMode") ) - mode = atoi(cgi_variable("ViewMode")); - ViewModeBoxes( mode ); - switch ( mode ) { - case 0: - parm_filter = FLAG_BASIC; - break; - case 1: - parm_filter = FLAG_ADVANCED; - break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; - } - d_printf("<table>\n"); - d_printf("<tr><td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Printer")); - d_printf("<td><select name=share>\n"); - if (snum < 0 || !lp_print_ok(snum)) - d_printf("<option value=\" \"> \n"); - for (i=0;i<lp_numservices();i++) { - s = lp_servicename(i); - if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) { - if (i >= iNumNonAutoPrintServices) - d_printf("<option %s value=\"%s\">[*]%s\n", - (share && strcmp(share,s)==0)?"SELECTED":"", - s, s); - else - d_printf("<option %s value=\"%s\">%s\n", - (share && strcmp(share,s)==0)?"SELECTED":"", - s, s); - } - } - d_printf("</select></td>"); - if (have_write_access) { - d_printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer")); - } - d_printf("</tr>"); - d_printf("</table>\n"); - - if (have_write_access) { - d_printf("<table>\n"); - d_printf("<tr><td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Printer")); - d_printf("<td><input type=text size=30 name=newshare></td></tr>\n"); - d_printf("</table>"); - } - - - if (snum >= 0) { - if (have_write_access) { - d_printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes")); - } - d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values")); - d_printf("<p>\n"); - } - - if (snum >= 0) { - d_printf("<table>\n"); - show_parameters(snum, 1, parm_filter, 1); - d_printf("</table>\n"); - } - d_printf("</FORM>\n"); -} - - -/** - * main function for SWAT. - **/ - int main(int argc, char *argv[]) -{ - extern char *optarg; - extern int optind; - int opt; - char *page; - - fault_setup(NULL); - umask(S_IWGRP | S_IWOTH); - -#if defined(HAVE_SET_AUTH_PARAMETERS) - set_auth_parameters(argc, argv); -#endif /* HAVE_SET_AUTH_PARAMETERS */ - - /* just in case it goes wild ... */ - alarm(300); - - setlinebuf(stdout); - - /* we don't want any SIGPIPE messages */ - BlockSignals(True,SIGPIPE); - - dbf = x_fopen("/dev/null", O_WRONLY, 0); - if (!dbf) dbf = x_stderr; - - /* we don't want stderr screwing us up */ - close(2); - open("/dev/null", O_WRONLY); - - while ((opt = getopt(argc, argv,"s:a")) != EOF) { - switch (opt) { - case 's': - pstrcpy(dyn_CONFIGFILE,optarg); - break; - case 'a': - demo_mode = True; - break; - } - } - - setup_logging(argv[0],DEBUG_FILE); - load_config(True); - iNumNonAutoPrintServices = lp_numservices(); - load_printers(); - - cgi_setup(dyn_SWATDIR, !demo_mode); - - print_header(); - - cgi_load_variables(); - - if (!file_exist(dyn_CONFIGFILE, NULL)) { - have_read_access = True; - have_write_access = True; - } else { - /* check if the authenticated user has write access - if not then - don't show write options */ - have_write_access = (access(dyn_CONFIGFILE,W_OK) == 0); - - /* if the user doesn't have read access to smb.conf then - don't let them view it */ - have_read_access = (access(dyn_CONFIGFILE,R_OK) == 0); - } - - show_main_buttons(); - - page = cgi_pathinfo(); - - /* Root gets full functionality */ - if (have_read_access && strcmp(page, "globals")==0) { - globals_page(); - } else if (have_read_access && strcmp(page,"shares")==0) { - shares_page(); - } else if (have_read_access && strcmp(page,"printers")==0) { - printers_page(); - } else if (have_read_access && strcmp(page,"status")==0) { - status_page(); - } else if (have_read_access && strcmp(page,"viewconfig")==0) { - viewconfig_page(); - } else if (strcmp(page,"passwd")==0) { - passwd_page(); - } else if (have_read_access && strcmp(page,"wizard")==0) { - wizard_page(); - } else if (have_read_access && strcmp(page,"wizard_params")==0) { - wizard_params_page(); - } else if (have_read_access && strcmp(page,"rewritecfg")==0) { - rewritecfg_file(); - } else { - welcome_page(); - } - - print_footer(); - return 0; -} - -/** @} **/ diff --git a/source4/wrepld/parser.c b/source4/wrepld/parser.c deleted file mode 100644 index b619cb0cef..0000000000 --- a/source4/wrepld/parser.c +++ /dev/null @@ -1,759 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Jean François Micouleau 1998-2002. - * - * 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 "wins_repl.h" - -extern TALLOC_CTX *mem_ctx; - -/**************************************************************************** -grow the send buffer if necessary -****************************************************************************/ -BOOL grow_buffer(struct BUFFER *buffer, int more) -{ - char *temp; - - DEBUG(10,("grow_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more)); - - /* grow by at least 256 bytes */ - if (more<256) - more=256; - - if (buffer->offset+more >= buffer->length) { - temp=(char *)talloc_realloc(mem_ctx, buffer->buffer, sizeof(char)* (buffer->length+more) ); - if (temp==NULL) { - DEBUG(0,("grow_buffer: can't grow buffer\n")); - return False; - } - buffer->length+=more; - buffer->buffer=temp; - } - - return True; -} - -/**************************************************************************** -check if the buffer has that much data -****************************************************************************/ -static BOOL check_buffer(struct BUFFER *buffer, int more) -{ - DEBUG(10,("check_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more)); - - if (buffer->offset+more > buffer->length) { - DEBUG(10,("check_buffer: buffer smaller than requested, size is: %d needed: %d\n", buffer->length, buffer->offset+more)); - return False; - } - - return True; -} - -/**************************************************************************** -decode a WINS_OWNER struct -****************************************************************************/ -static void decode_wins_owner(struct BUFFER *inbuf, WINS_OWNER *wins_owner) -{ - if(!check_buffer(inbuf, 24)) - return; - - wins_owner->address.s_addr=IVAL(inbuf->buffer, inbuf->offset); - wins_owner->max_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+4))<<32; - wins_owner->max_version|=RIVAL(inbuf->buffer, inbuf->offset+8); - wins_owner->min_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+12))<<32; - wins_owner->min_version|=RIVAL(inbuf->buffer, inbuf->offset+16); - wins_owner->type=RIVAL(inbuf->buffer, inbuf->offset+20); - inbuf->offset+=24; - -} - -/**************************************************************************** -decode a WINS_NAME struct -****************************************************************************/ -static void decode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name) -{ - char *p; - int i; - - if(!check_buffer(outbuf, 40)) - return; - - wins_name->name_len=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - memcpy(wins_name->name,outbuf->buffer+outbuf->offset, 15); - wins_name->name[15]='\0'; - if((p = strchr(wins_name->name,' ')) != NULL) - *p = 0; - - outbuf->offset+=15; - - wins_name->type=(int)outbuf->buffer[outbuf->offset++]; - - /* - * fix to bug in WINS replication, - * present in all versions including W2K SP2 ! - */ - if (wins_name->name[0]==0x1B) { - wins_name->name[0]=(char)wins_name->type; - wins_name->type=0x1B; - } - - wins_name->empty=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - - wins_name->name_flag=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - wins_name->group_flag=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf->buffer, outbuf->offset))<<32; - outbuf->offset+=4; - wins_name->id|=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - - /* special groups have multiple address */ - if (wins_name->name_flag & 2) { - if(!check_buffer(outbuf, 4)) - return; - wins_name->num_ip=IVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - } - else - wins_name->num_ip=1; - - if(!check_buffer(outbuf, 4)) - return; - wins_name->owner.s_addr=IVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - - if (wins_name->name_flag & 2) { - wins_name->others=(struct in_addr *)talloc(mem_ctx, sizeof(struct in_addr)*wins_name->num_ip); - if (wins_name->others==NULL) - return; - - if(!check_buffer(outbuf, 4*wins_name->num_ip)) - return; - for (i=0; i<wins_name->num_ip; i++) { - wins_name->others[i].s_addr=IVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - } - } - - if(!check_buffer(outbuf, 4)) - return; - wins_name->foo=RIVAL(outbuf->buffer, outbuf->offset); - outbuf->offset+=4; - -} - -/**************************************************************************** -decode a update notification request -****************************************************************************/ -static void decode_update_notify_request(struct BUFFER *inbuf, UPDATE_NOTIFY_REQUEST *un_rq) -{ - int i; - - if(!check_buffer(inbuf, 4)) - return; - un_rq->partner_count=RIVAL(inbuf->buffer, inbuf->offset); - inbuf->offset+=4; - - un_rq->wins_owner=(WINS_OWNER *)talloc(mem_ctx, un_rq->partner_count*sizeof(WINS_OWNER)); - if (un_rq->wins_owner==NULL) - return; - - for (i=0; i<un_rq->partner_count; i++) - decode_wins_owner(inbuf, &un_rq->wins_owner[i]); - - if(!check_buffer(inbuf, 4)) - return; - un_rq->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset); - inbuf->offset+=4; -} - -/**************************************************************************** -decode a send entries request -****************************************************************************/ -static void decode_send_entries_request(struct BUFFER *inbuf, SEND_ENTRIES_REQUEST *se_rq) -{ - decode_wins_owner(inbuf, &se_rq->wins_owner); -} - -/**************************************************************************** -decode a send entries reply -****************************************************************************/ -static void decode_send_entries_reply(struct BUFFER *inbuf, SEND_ENTRIES_REPLY *se_rp) -{ - int i; - - if(!check_buffer(inbuf, 4)) - return; - se_rp->max_names = RIVAL(inbuf->buffer, inbuf->offset); - inbuf->offset+=4; - - se_rp->wins_name=(WINS_NAME *)talloc(mem_ctx, se_rp->max_names*sizeof(WINS_NAME)); - if (se_rp->wins_name==NULL) - return; - - for (i=0; i<se_rp->max_names; i++) - decode_wins_name(inbuf, &se_rp->wins_name[i]); -} - -/**************************************************************************** -decode a add version number map table reply -****************************************************************************/ -static void decode_add_version_number_map_table_reply(struct BUFFER *inbuf, AVMT_REP *avmt_rep) -{ - int i; - - if(!check_buffer(inbuf, 4)) - return; - - avmt_rep->partner_count=RIVAL(inbuf->buffer, inbuf->offset); - inbuf->offset+=4; - - avmt_rep->wins_owner=(WINS_OWNER *)talloc(mem_ctx, avmt_rep->partner_count*sizeof(WINS_OWNER)); - if (avmt_rep->wins_owner==NULL) - return; - - for (i=0; i<avmt_rep->partner_count; i++) - decode_wins_owner(inbuf, &avmt_rep->wins_owner[i]); - - if(!check_buffer(inbuf, 4)) - return; - avmt_rep->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset); - inbuf->offset+=4; -} - -/**************************************************************************** -decode a replicate packet and fill a structure -****************************************************************************/ -static void decode_replicate(struct BUFFER *inbuf, REPLICATE *rep) -{ - if(!check_buffer(inbuf, 4)) - return; - - rep->msg_type = RIVAL(inbuf->buffer, inbuf->offset); - - inbuf->offset+=4; - - switch (rep->msg_type) { - case 0: - break; - case 1: - /* add version number map table reply */ - decode_add_version_number_map_table_reply(inbuf, &rep->avmt_rep); - break; - case 2: - /* send entry request */ - decode_send_entries_request(inbuf, &rep->se_rq); - break; - case 3: - /* send entry request */ - decode_send_entries_reply(inbuf, &rep->se_rp); - break; - case 4: - /* update notification request */ - decode_update_notify_request(inbuf, &rep->un_rq); - break; - default: - DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type)); - break; - } -} - -/**************************************************************************** -read the generic header and fill the struct. -****************************************************************************/ -static void read_generic_header(struct BUFFER *inbuf, generic_header *q) -{ - if(!check_buffer(inbuf, 16)) - return; - - q->data_size = RIVAL(inbuf->buffer, inbuf->offset+0); - q->opcode = RIVAL(inbuf->buffer, inbuf->offset+4); - q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+8); - q->mess_type = RIVAL(inbuf->buffer, inbuf->offset+12); -} - -/******************************************************************* -decode a start association request -********************************************************************/ -static void decode_start_assoc_request(struct BUFFER *inbuf, START_ASSOC_REQUEST *q) -{ - if(!check_buffer(inbuf, 8)) - return; - - q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+0); - q->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4); - q->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6); -} - -/******************************************************************* -decode a start association reply -********************************************************************/ -static void decode_start_assoc_reply(struct BUFFER *inbuf, START_ASSOC_REPLY *r) -{ - if(!check_buffer(inbuf, 8)) - return; - - r->assoc_ctx=RIVAL(inbuf->buffer, inbuf->offset+0); - r->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4); - r->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6); -} - -/******************************************************************* -decode a start association reply -********************************************************************/ -static void decode_stop_assoc(struct BUFFER *inbuf, STOP_ASSOC *r) -{ - if(!check_buffer(inbuf, 4)) - return; - - r->reason=RIVAL(inbuf->buffer, inbuf->offset); -} - -/**************************************************************************** -decode a packet and fill a generic structure -****************************************************************************/ -void decode_generic_packet(struct BUFFER *inbuf, GENERIC_PACKET *q) -{ - read_generic_header(inbuf, &q->header); - - inbuf->offset+=16; - - switch (q->header.mess_type) { - case 0: - decode_start_assoc_request(inbuf, &q->sa_rq); - break; - case 1: - decode_start_assoc_reply(inbuf, &q->sa_rp); - break; - case 2: - decode_stop_assoc(inbuf, &q->so); - break; - case 3: - decode_replicate(inbuf, &q->rep); - break; - default: - DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type)); - break; - } -} - -/**************************************************************************** -encode a WINS_OWNER struct -****************************************************************************/ -static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner) -{ - if (!grow_buffer(outbuf, 24)) - return; - - SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32)); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff)); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type); - outbuf->offset+=4; - -} - -/**************************************************************************** -encode a WINS_NAME struct -****************************************************************************/ -static void encode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name) -{ - int i; - - if (!grow_buffer(outbuf, 48+(4*wins_name->num_ip))) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_len); - outbuf->offset+=4; - - memset(outbuf->buffer+outbuf->offset, ' ', 15); - - /* to prevent copying the leading \0 */ - memcpy(outbuf->buffer+outbuf->offset, wins_name->name, strlen(wins_name->name)); - outbuf->offset+=15; - - outbuf->buffer[outbuf->offset++]=(char)wins_name->type; - - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->empty); - outbuf->offset+=4; - - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_flag); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->group_flag); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id>>32); - outbuf->offset+=4; - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id); - outbuf->offset+=4; - - if (wins_name->name_flag & 2) { - SIVAL(outbuf->buffer, outbuf->offset, wins_name->num_ip); - outbuf->offset+=4; - } - - SIVAL(outbuf->buffer, outbuf->offset, wins_name->owner.s_addr); - outbuf->offset+=4; - - if (wins_name->name_flag & 2) { - for (i=0;i<wins_name->num_ip;i++) { - SIVAL(outbuf->buffer, outbuf->offset, wins_name->others[i].s_addr); - outbuf->offset+=4; - } - } - - RSIVAL(outbuf->buffer, outbuf->offset, wins_name->foo); - outbuf->offset+=4; -} - -/**************************************************************************** -encode a update notification request -****************************************************************************/ -static void encode_update_notify_request(struct BUFFER *outbuf, UPDATE_NOTIFY_REQUEST *un_rq) -{ - int i; - - if (!grow_buffer(outbuf, 8)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, un_rq->partner_count); - outbuf->offset+=4; - - for (i=0; i<un_rq->partner_count; i++) - encode_wins_owner(outbuf, &un_rq->wins_owner[i]); - - SIVAL(outbuf->buffer, outbuf->offset, un_rq->initiating_wins_server.s_addr); - outbuf->offset+=4; - -} - -/**************************************************************************** -decode a send entries request -****************************************************************************/ -static void encode_send_entries_request(struct BUFFER *outbuf, SEND_ENTRIES_REQUEST *se_rq) -{ - encode_wins_owner(outbuf, &se_rq->wins_owner); -} - -/**************************************************************************** -decode a send entries reply -****************************************************************************/ -static void encode_send_entries_reply(struct BUFFER *outbuf, SEND_ENTRIES_REPLY *se_rp) -{ - int i; - - if (!grow_buffer(outbuf, 4)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, se_rp->max_names); - outbuf->offset+=4; - - for (i=0; i<se_rp->max_names; i++) - encode_wins_name(outbuf, &se_rp->wins_name[i]); - -} - -/**************************************************************************** -encode a add version number map table reply -****************************************************************************/ -static void encode_add_version_number_map_table_reply(struct BUFFER *outbuf, AVMT_REP *avmt_rep) -{ - int i; - - if (!grow_buffer(outbuf, 8)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, avmt_rep->partner_count); - outbuf->offset+=4; - - for (i=0; i<avmt_rep->partner_count; i++) - encode_wins_owner(outbuf, &avmt_rep->wins_owner[i]); - - SIVAL(outbuf->buffer, outbuf->offset, avmt_rep->initiating_wins_server.s_addr); - outbuf->offset+=4; - -} - -/**************************************************************************** -decode a replicate packet and fill a structure -****************************************************************************/ -static void encode_replicate(struct BUFFER *outbuf, REPLICATE *rep) -{ - if (!grow_buffer(outbuf, 4)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, rep->msg_type); - outbuf->offset+=4; - - switch (rep->msg_type) { - case 0: - break; - case 1: - /* add version number map table reply */ - encode_add_version_number_map_table_reply(outbuf, &rep->avmt_rep); - break; - case 2: - /* send entry request */ - encode_send_entries_request(outbuf, &rep->se_rq); - break; - case 3: - /* send entry request */ - encode_send_entries_reply(outbuf, &rep->se_rp); - break; - case 4: - /* update notification request */ - encode_update_notify_request(outbuf, &rep->un_rq); - break; - default: - DEBUG(0,("encode_replicate: unknown message type:%d\n", rep->msg_type)); - break; - } -} - -/**************************************************************************** -write the generic header. -****************************************************************************/ -static void write_generic_header(struct BUFFER *outbuf, generic_header *r) -{ - RSIVAL(outbuf->buffer, 0, r->data_size); - RSIVAL(outbuf->buffer, 4, r->opcode); - RSIVAL(outbuf->buffer, 8, r->assoc_ctx); - RSIVAL(outbuf->buffer,12, r->mess_type); -} - -/******************************************************************* -decode a start association request -********************************************************************/ -static void encode_start_assoc_request(struct BUFFER *outbuf, START_ASSOC_REQUEST *q) -{ - if (!grow_buffer(outbuf, 45)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, q->assoc_ctx); - RSSVAL(outbuf->buffer, outbuf->offset+4, q->min_ver); - RSSVAL(outbuf->buffer, outbuf->offset+6, q->maj_ver); - - outbuf->offset=45; -} - -/******************************************************************* -decode a start association reply -********************************************************************/ -static void encode_start_assoc_reply(struct BUFFER *outbuf, START_ASSOC_REPLY *r) -{ - if (!grow_buffer(outbuf, 45)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, r->assoc_ctx); - RSSVAL(outbuf->buffer, outbuf->offset+4, r->min_ver); - RSSVAL(outbuf->buffer, outbuf->offset+6, r->maj_ver); - - outbuf->offset=45; -} - -/******************************************************************* -decode a start association reply -********************************************************************/ -static void encode_stop_assoc(struct BUFFER *outbuf, STOP_ASSOC *r) -{ - if (!grow_buffer(outbuf, 44)) - return; - - RSIVAL(outbuf->buffer, outbuf->offset, r->reason); - - outbuf->offset=44; -} - -/**************************************************************************** -write the generic header size. -****************************************************************************/ -static void write_generic_header_size(generic_header *r, int size) -{ - /* the buffer size is the total size minus the size field */ - r->data_size=size-4; -} - -/**************************************************************************** -encode a packet and read a generic structure -****************************************************************************/ -void encode_generic_packet(struct BUFFER *outbuf, GENERIC_PACKET *q) -{ - if (!grow_buffer(outbuf, 16)) - return; - - outbuf->offset=16; - - switch (q->header.mess_type) { - case 0: - encode_start_assoc_request(outbuf, &q->sa_rq); - break; - case 1: - encode_start_assoc_reply(outbuf, &q->sa_rp); - break; - case 2: - encode_stop_assoc(outbuf, &q->so); - break; - case 3: - encode_replicate(outbuf, &q->rep); - break; - default: - DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q->header.mess_type)); - break; - } - - write_generic_header_size(&q->header, outbuf->offset); - write_generic_header(outbuf, &q->header); -} - - -/**************************************************************************** -dump a WINS_OWNER structure -****************************************************************************/ -static void dump_wins_owner(WINS_OWNER *wins_owner) -{ - DEBUGADD(10,("\t\t\t\taddress : %s\n", inet_ntoa(wins_owner->address))); - DEBUGADD(10,("\t\t\t\tmax version: %d\n", (int)wins_owner->max_version)); - DEBUGADD(10,("\t\t\t\tmin version: %d\n", (int)wins_owner->min_version)); - DEBUGADD(10,("\t\t\t\ttype : %d\n", wins_owner->type)); -} - -/**************************************************************************** -dump a WINS_NAME structure -****************************************************************************/ -static void dump_wins_name(WINS_NAME *wins_name) -{ - fstring name; - int i; - - strncpy(name, wins_name->name, 15); - - DEBUGADD(10,("name: %d, %s<%02x> %x,%x, %d %s %d ", wins_name->name_len, name, wins_name->type, - wins_name->name_flag, wins_name->group_flag, (int)wins_name->id, - inet_ntoa(wins_name->owner), wins_name->num_ip)); - - if (wins_name->num_ip!=1) - for (i=0; i<wins_name->num_ip; i++) - DEBUGADD(10,("%s ", inet_ntoa(wins_name->others[i]))); - - DEBUGADD(10,("\n")); -} - -/**************************************************************************** -dump a replicate structure -****************************************************************************/ -static void dump_replicate(REPLICATE *rep) -{ - int i; - - DEBUGADD(5,("\t\tmsg_type: %d ", rep->msg_type)); - - switch (rep->msg_type) { - case 0: - DEBUGADD(5,("(Add Version Map Table Request)\n")); - break; - case 1: - DEBUGADD(5,("(Add Version Map Table Reply)\n")); - DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep->avmt_rep.partner_count)); - for (i=0; i<rep->avmt_rep.partner_count; i++) - dump_wins_owner(&rep->avmt_rep.wins_owner[i]); - DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->avmt_rep.initiating_wins_server))); - break; - case 2: - DEBUGADD(5,("(Send Entries Request)\n")); - dump_wins_owner(&rep->se_rq.wins_owner); - break; - case 3: - DEBUGADD(5,("(Send Entries Reply)\n")); - DEBUGADD(5,("\t\t\tmax_names : %d\n", rep->se_rp.max_names)); - for (i=0; i<rep->se_rp.max_names; i++) - dump_wins_name(&rep->se_rp.wins_name[i]); - break; - case 4: - DEBUGADD(5,("(Update Notify Request)\n")); - DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep->un_rq.partner_count)); - for (i=0; i<rep->un_rq.partner_count; i++) - dump_wins_owner(&rep->un_rq.wins_owner[i]); - DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->un_rq.initiating_wins_server))); - break; - default: - DEBUG(5,("\n")); - break; - } -} - -/**************************************************************************** -dump a generic structure -****************************************************************************/ -void dump_generic_packet(GENERIC_PACKET *q) -{ - DEBUG(5,("dump_generic_packet:\n")); - DEBUGADD(5,("\tdata_size: %08x\n", q->header.data_size)); - DEBUGADD(5,("\topcode : %08x\n", q->header.opcode)); - DEBUGADD(5,("\tassoc_ctx: %08x\n", q->header.assoc_ctx)); - DEBUGADD(5,("\tmess_type: %08x ", q->header.mess_type)); - - switch (q->header.mess_type) { - case 0: - DEBUGADD(5,("(Start Association Request)\n")); - DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rq.assoc_ctx)); - DEBUGADD(5,("\t\tmin_ver : %04x\n", q->sa_rq.min_ver)); - DEBUGADD(5,("\t\tmaj_ver : %04x\n", q->sa_rq.maj_ver)); - break; - case 1: - DEBUGADD(5,("(Start Association Reply)\n")); - DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rp.assoc_ctx)); - DEBUGADD(5,("\t\tmin_ver : %04x\n", q->sa_rp.min_ver)); - DEBUGADD(5,("\t\tmaj_ver : %04x\n", q->sa_rp.maj_ver)); - break; - case 2: - DEBUGADD(5,("(Stop Association)\n")); - DEBUGADD(5,("\t\treason: %08x\n", q->so.reason)); - break; - case 3: - DEBUGADD(5,("(Replication Message)\n")); - dump_replicate(&q->rep); - break; - default: - DEBUG(5,("\n")); - break; - } - -} - -/**************************************************************************** -generate a stop packet -****************************************************************************/ -void stop_packet(GENERIC_PACKET *q, GENERIC_PACKET *r, int reason) -{ - r->header.opcode=OPCODE_NON_NBT; - r->header.assoc_ctx=get_server_assoc(q->header.assoc_ctx); - r->header.mess_type=MESSAGE_TYPE_STOP_ASSOC; - r->so.reason=reason; - -} - - diff --git a/source4/wrepld/partners.c b/source4/wrepld/partners.c deleted file mode 100644 index 2387f5b45f..0000000000 --- a/source4/wrepld/partners.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - Unix SMB/CIFS implementation. - process incoming packets - main loop - Copyright (C) Jean François Micouleau 1998-2002. - - 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 "wins_repl.h" - -/* we can exchange info with 64 partners at any given time */ -WINS_PARTNER current_partners[64]; -int total_current_partners; - -/******************************************************************* -verify if we know this partner -********************************************************************/ -BOOL check_partner(int assoc) -{ - int i; - - DEBUG(5,("check_partner: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==assoc) - return True; - - return False; -} - -/******************************************************************* -add a new entry to the list -********************************************************************/ -BOOL add_partner(int client_assoc, int server_assoc, BOOL pull, BOOL push) -{ - DEBUG(5,("add_partner: total_current_partners: %d\n", total_current_partners)); - - if (total_current_partners==64) - return False; - - current_partners[total_current_partners].client_assoc=client_assoc; - current_partners[total_current_partners].server_assoc=server_assoc; - current_partners[total_current_partners].pull_partner=pull; - current_partners[total_current_partners].push_partner=push; - - total_current_partners++; - - return True; -} - -/******************************************************************* -remove an entry to the list -********************************************************************/ -BOOL remove_partner(int client_assoc) -{ - int i,j; - - DEBUG(5,("remove_partner: total_current_partners: %d\n", total_current_partners)); - - for (i=0; current_partners[i].client_assoc!=client_assoc && i<total_current_partners; i++) - ; - - if (i==total_current_partners) - return False; - - for (j=i+1; j<total_current_partners; j++) { - current_partners[j-1].client_assoc=current_partners[j].client_assoc; - current_partners[j-1].server_assoc=current_partners[j].server_assoc; - current_partners[j-1].pull_partner=current_partners[j].pull_partner; - current_partners[j-1].push_partner=current_partners[j].push_partner; - current_partners[j-1].partner_server.s_addr=current_partners[j].partner_server.s_addr; - current_partners[j-1].other_server.s_addr=current_partners[j].other_server.s_addr; - } - - total_current_partners--; - - return True; -} - -/******************************************************************* -link the client and server context -********************************************************************/ -BOOL update_server_partner(int client_assoc, int server_assoc) -{ - int i; - - DEBUG(5,("update_server_partner: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==client_assoc) { - current_partners[i].server_assoc=server_assoc; - return True; - } - - return False; -} - -/******************************************************************* -verify if it's a pull partner -********************************************************************/ -BOOL check_pull_partner(int assoc) -{ - int i; - - DEBUG(5,("check_pull_partner: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==assoc && - current_partners[i].pull_partner==True) - return True; - - return False; -} - -/******************************************************************* -verify if it's a push partner -********************************************************************/ -BOOL check_push_partner(int assoc) -{ - int i; - - DEBUG(5,("check_push_partner: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==assoc && - current_partners[i].push_partner==True) - return True; - - return False; -} - -/******************************************************************* -return the server ctx linked to the client ctx -********************************************************************/ -int get_server_assoc(int assoc) -{ - int i; - - DEBUG(5,("get_server_assoc: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==assoc) - return current_partners[i].server_assoc; - - return 0; -} - - -/******************************************************************* -link the client and server context -********************************************************************/ -BOOL write_server_assoc_table(int client_assoc, struct in_addr partner, struct in_addr server) -{ - int i; - - DEBUG(5,("write_server_assoc_table: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==client_assoc) { - current_partners[i].partner_server=partner; - current_partners[i].other_server=server; - return True; - } - - return False; -} - -/******************************************************************* -link the client and server context -********************************************************************/ -BOOL get_server_assoc_table(int client_assoc, struct in_addr *partner, struct in_addr *server) -{ - int i; - - DEBUG(5,("get_server_assoc_table: total_current_partners: %d\n", total_current_partners)); - - for (i=0; i<total_current_partners; i++) - if (current_partners[i].client_assoc==client_assoc) { - partner->s_addr=current_partners[i].partner_server.s_addr; - server->s_addr=current_partners[i].other_server.s_addr; - return True; - } - - return False; -} - - diff --git a/source4/wrepld/process.c b/source4/wrepld/process.c deleted file mode 100644 index 1f96dc996c..0000000000 --- a/source4/wrepld/process.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - Unix SMB/CIFS implementation. - process incoming packets - main loop - Copyright (C) Jean François Micouleau 1998-2002. - - 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 "wins_repl.h" - -extern fd_set *listen_set; -extern int listen_number; -extern int *sock_array; - -WINS_OWNER global_wins_table[64][64]; -int partner_count; - -TALLOC_CTX *mem_ctx; - -#define WINS_LIST "wins.tdb" -#define INFO_VERSION "INFO/version" -#define INFO_COUNT "INFO/num_entries" -#define INFO_ID_HIGH "INFO/id_high" -#define INFO_ID_LOW "INFO/id_low" -#define ENTRY_PREFIX "ENTRY/" - - -/******************************************************************* -fill the header of a reply. -********************************************************************/ -static void fill_header(GENERIC_PACKET *g, int opcode, int ctx, int mess) -{ - if (g==NULL) - return; - - g->header.opcode=opcode; - g->header.assoc_ctx=ctx; - g->header.mess_type=mess; -} - -/******************************************************************* -dump the global table, that's a debug code. -********************************************************************/ -static void dump_global_table(void) -{ - int i,j; - - for (i=0;i<partner_count;i++) { - DEBUG(10,("\n%d ", i)); - for (j=0; global_wins_table[i][j].address.s_addr!=0; j++) - DEBUG(10,("%s:%d \t", inet_ntoa(global_wins_table[i][j].address), - (int)global_wins_table[i][j].max_version)); - } - DEBUG(10,("\n")); -} - -/******************************************************************* -start association -********************************************************************/ -static void start_assoc_process(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - /* - * add this request to our current wins partners list - * this list is used to know with who we are in contact - * - */ - r->sa_rp.assoc_ctx=time(NULL); - fill_header(r, OPCODE_NON_NBT, q->sa_rq.assoc_ctx, MESSAGE_TYPE_START_ASSOC_REPLY); - - /* reply we are a NT4 server */ - - /* w2K is min=2, maj=5 */ - - r->sa_rp.min_ver=1; - r->sa_rp.maj_ver=1; - - add_partner(r->sa_rp.assoc_ctx, q->sa_rq.assoc_ctx, False, False); -} - -/******************************************************************* -start association reply -********************************************************************/ -static void start_assoc_reply(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - int i; - - /* check if we have already registered this client */ - if (!check_partner(q->header.assoc_ctx)) { - DEBUG(0,("start_assoc_reply: unknown client\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - if (!update_server_partner(q->header.assoc_ctx, q->sa_rp.assoc_ctx)) { - DEBUG(0,("start_assoc_reply: can't update server ctx\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - /* if pull, request map table */ - if (check_pull_partner(q->header.assoc_ctx)) { - fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE); - - r->rep.msg_type=MESSAGE_REP_ADD_VERSION_REQUEST; - DEBUG(5,("start_assoc_reply: requesting map table\n")); - - return; - } - - /* if push, send our table */ - if (check_push_partner(q->header.assoc_ctx)) { - fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE); - r->rep.msg_type=MESSAGE_REP_UPDATE_NOTIFY_REQUEST; - r->rep.un_rq.partner_count=partner_count; - - r->rep.un_rq.wins_owner=(WINS_OWNER *)talloc(mem_ctx, partner_count*sizeof(WINS_OWNER)); - if (r->rep.un_rq.wins_owner==NULL) { - DEBUG(0,("start_assoc_reply: can't alloc memory\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - for (i=0; i<partner_count; i++) - r->rep.un_rq.wins_owner[i]=global_wins_table[0][i]; - - DEBUG(5,("start_assoc_reply: sending update table\n")); - return; - } - - /* neither push/pull, stop */ - /* we should not come here */ - DEBUG(0,("we have a partner which is neither push nor pull !\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); -} - -/**************************************************************************** -initialise and fill the in-memory partner table. -****************************************************************************/ -int init_wins_partner_table(void) -{ - int i=1,j=0,k; - char **partner = str_list_make(lp_wins_partners(), NULL); - - if (partner==NULL) { - DEBUG(0,("wrepld: no partner list in smb.conf, exiting\n")); - exit_server("normal exit"); - return(0); - } - - DEBUG(4, ("init_wins_partner_table: partners: %s\n", lp_wins_partners())); - - global_wins_table[0][0].address=*iface_n_ip(0); - global_wins_table[0][0].max_version=0; - global_wins_table[0][0].min_version=0; - global_wins_table[0][0].type=0; - - while (partner[j]!=NULL) { - DEBUG(3,("init_wins_partner_table, adding partner: %s\n", partner[j])); - - global_wins_table[0][i].address=*interpret_addr2(partner[j]); - global_wins_table[0][i].max_version=0; - global_wins_table[0][i].min_version=0; - global_wins_table[0][i].type=0; - global_wins_table[0][i].last_pull=0; - global_wins_table[0][i].last_push=0; - - i++; - j++; - } - - for (k=1; k<i;k++) - for (j=0; j<i; j++) - global_wins_table[k][j]=global_wins_table[0][j]; - - str_list_free (&partner); - - return i; -} - -/**************************************************************************** -read the last ID from the wins tdb file. -****************************************************************************/ -static void get_our_last_id(WINS_OWNER *wins_owner) -{ - TDB_CONTEXT *tdb; - - tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!tdb) { - DEBUG(2,("get_our_last_id: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); - return; - } - - wins_owner->max_version=((SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_HIGH))<<32 | - (SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_LOW); - - tdb_close(tdb); -} - -/**************************************************************************** -send the list of wins server we know. -****************************************************************************/ -static void send_version_number_map_table(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - int i; - int s_ctx=get_server_assoc(q->header.assoc_ctx); - - if (s_ctx==0) { - DEBUG(5, ("send_version_number_map_table: request for a partner not in our table\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - /* - * return an array of wins servers, we are partner with. - * each entry contains the IP address and the version info - * version: ID of the last entry we've got - */ - - /* the first wins server must be self */ - - /* - * get our last ID from the wins database - * it can have been updated since last read - * as nmbd got registration/release. - */ - get_our_last_id(&global_wins_table[0][0]); - - r->rep.avmt_rep.wins_owner=(WINS_OWNER *)talloc(mem_ctx, partner_count*sizeof(WINS_OWNER)); - if (r->rep.avmt_rep.wins_owner==NULL) { - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - DEBUG(5,("send_version_number_map_table: partner_count: %d\n", partner_count)); - - for (i=0; i<partner_count; i++) { - DEBUG(5,("send_version_number_map_table, partner: %d -> %s, \n", i, inet_ntoa(global_wins_table[0][i].address))); - r->rep.avmt_rep.wins_owner[i]=global_wins_table[0][i]; - } - - r->rep.msg_type=1; - r->rep.avmt_rep.partner_count=partner_count; - r->rep.avmt_rep.initiating_wins_server.s_addr=0; /* blatant lie, NT4/w2K do the same ! */ - fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE); -} - -/**************************************************************************** -for a given partner, ask it to send entries we don't have. -****************************************************************************/ -static BOOL check_partners_and_send_entries(GENERIC_PACKET *q, GENERIC_PACKET *r, int partner) -{ - int server; - int other; - SMB_BIG_UINT temp; - SMB_BIG_UINT current; - - - /* - * we check if our partner has more records than us. - * we need to check more than our direct partners as - * we can have this case: - * us: A, partners: B,C, indirect partner: D - * A<->B, A<->C, B<->D, C<->D - * - * So if we're talking to B, we need to check if between - * B and C, which one have more records about D. - * and also check if we don't already have the records. - */ - - - /* check all servers even indirect */ - for (server=1; global_wins_table[0][server].address.s_addr!=0; server++) { - current = global_wins_table[partner][server].max_version; - - temp=0; - - for (other=1; other<partner_count; other++) { - /* skip the partner itself */ - if (other==partner) - continue; - - if (global_wins_table[other][server].max_version > temp) - temp=global_wins_table[other][server].max_version; - } - - if (current >= temp && current > global_wins_table[0][server].max_version) { - /* - * it has more records than every body else and more than us, - * ask it the difference between what we have and what it has - */ - fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE); - - r->rep.msg_type=MESSAGE_REP_SEND_ENTRIES_REQUEST; - r->rep.se_rq.wins_owner.address=global_wins_table[partner][server].address; - - r->rep.se_rq.wins_owner.max_version=global_wins_table[partner][server].max_version; - r->rep.se_rq.wins_owner.min_version=global_wins_table[0][server].max_version; - r->rep.se_rq.wins_owner.type=0; - - write_server_assoc_table(q->header.assoc_ctx, global_wins_table[0][partner].address, global_wins_table[partner][server].address); - - /* - * and we update our version for this server - * as we can't use the IDs returned in the send_entries function - * the max ID can be larger than the largest ID returned - */ - - global_wins_table[0][server].max_version=global_wins_table[partner][server].max_version; - - return True; - } - } - return False; -} - -/**************************************************************************** -receive the list of wins server we know. -****************************************************************************/ -static void receive_version_number_map_table(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - fstring peer; - struct in_addr addr; - int i,j,k,l; - int s_ctx=get_server_assoc(q->header.assoc_ctx); - - if (s_ctx==0) { - DEBUG(5, ("receive_version_number_map_table: request for a partner not in our table\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - fstrcpy(peer,get_socket_addr(q->fd)); - addr=*interpret_addr2(peer); - - get_our_last_id(&global_wins_table[0][0]); - - DEBUG(5,("receive_version_number_map_table: received a map of %d server from: %s\n", - q->rep.avmt_rep.partner_count ,inet_ntoa(q->rep.avmt_rep.initiating_wins_server))); - DEBUG(5,("real peer is: %s\n", peer)); - - for (i=0; global_wins_table[0][i].address.s_addr!=addr.s_addr && i<partner_count;i++) - ; - - if (i==partner_count) { - DEBUG(5,("receive_version_number_map_table: unknown partner: %s\n", peer)); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - for (j=0; j<q->rep.avmt_rep.partner_count;j++) { - /* - * search if we already have this entry or if it's a new one - * it can be a new one in case of propagation - */ - for (k=0; global_wins_table[0][k].address.s_addr!=0 && - global_wins_table[0][k].address.s_addr!=q->rep.avmt_rep.wins_owner[j].address.s_addr; k++); - - global_wins_table[i][k].address.s_addr=q->rep.avmt_rep.wins_owner[j].address.s_addr; - global_wins_table[i][k].max_version=q->rep.avmt_rep.wins_owner[j].max_version; - global_wins_table[i][k].min_version=q->rep.avmt_rep.wins_owner[j].min_version; - global_wins_table[i][k].type=q->rep.avmt_rep.wins_owner[j].type; - - /* - * in case it's a new one, rewrite the address for all the partner - * to reserve the slot. - */ - - for(l=0; l<partner_count; l++) - global_wins_table[l][k].address.s_addr=q->rep.avmt_rep.wins_owner[j].address.s_addr; - } - - dump_global_table(); - - /* - * if this server have newer records than what we have - * for several wins servers, we need to ask it. - * Alas a send entry request is only on one server. - * So in the send entry reply, we'll ask for the next server if required. - */ - - if (check_partners_and_send_entries(q, r, i)) - return; - - /* it doesn't have more entries than us */ - stop_packet(q, r, STOP_REASON_USER_REASON); -} - -/**************************************************************************** -add an entry to the wins list we'll send. -****************************************************************************/ -static BOOL add_record_to_winsname(WINS_NAME **wins_name, int *max_names, char *name, int type, int wins_flags, int id, struct in_addr *ip_list, int num_ips) -{ - WINS_NAME *temp_list; - int i; - int current=*max_names; - - temp_list=talloc_realloc(mem_ctx, *wins_name, (current+1)*sizeof(WINS_NAME)); - if (temp_list==NULL) - return False; - - temp_list[current].name_len=0x11; - - safe_strcpy(temp_list[current].name, name, 15); - - temp_list[current].type=type; - temp_list[current].empty=0; - - temp_list[current].name_flag=wins_flags; - - if ( (wins_flags&0x03) == 1 || (wins_flags&0x03)==2) - temp_list[current].group_flag=0x01000000; - else - temp_list[current].group_flag=0x00000000; - - temp_list[current].id=id; - - temp_list[current].owner.s_addr=ip_list[0].s_addr; - - if (temp_list[current].name_flag & 2) { - temp_list[current].num_ip=num_ips; - temp_list[current].others=(struct in_addr *)talloc(mem_ctx, sizeof(struct in_addr)*num_ips); - if (temp_list[current].others==NULL) - return False; - - for (i=0; i<num_ips; i++) - temp_list[current].others[i].s_addr=ip_list[i].s_addr; - - } else - temp_list[current].num_ip=1; - - temp_list[current].foo=0xffffffff; - - *wins_name=temp_list; - - return True; -} - -/**************************************************************************** -send the list of name we have. -****************************************************************************/ -static void send_entry_request(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - int max_names=0; - int i; - time_t time_now = time(NULL); - WINS_OWNER *wins_owner; - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf, newkey; - int s_ctx=get_server_assoc(q->header.assoc_ctx); - int num_interfaces = iface_count(); - - if (s_ctx==0) { - DEBUG(1, ("send_entry_request: request for a partner not in our table\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - - wins_owner=&q->rep.se_rq.wins_owner; - r->rep.se_rp.wins_name=NULL; - - DEBUG(3,("send_entry_request: we have been asked to send the list of wins records\n")); - DEBUGADD(3,("owned by: %s and between min: %d and max: %d\n", inet_ntoa(wins_owner->address), - (int)wins_owner->min_version, (int)wins_owner->max_version)); - - /* - * if we are asked to send records owned by us - * we overwrite the wins ip with 0.0.0.0 - * to make it easy in case of multihomed - */ - - for (i=0; i<num_interfaces; i++) - if (ip_equal(wins_owner->address, *iface_n_ip(i))) { - wins_owner->address=*interpret_addr2("0.0.0.0"); - break; - } - - - tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!tdb) { - DEBUG(2,("send_entry_request: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); - return; - } - - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - fstring name_type; - pstring name, ip_str; - char *p; - int type = 0; - int nb_flags; - int ttl; - unsigned int num_ips; - int low, high; - SMB_BIG_UINT version; - struct in_addr wins_ip; - struct in_addr *ip_list; - int wins_flags; - int len; - - if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0) - continue; - - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; - - fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX)); - pstrcpy(name, name_type); - - if((p = strchr(name,'#')) != NULL) { - *p = 0; - sscanf(p+1,"%x",&type); - } - - len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd", - &nb_flags, - &high, - &low, - ip_str, - &ttl, - &num_ips, - &wins_flags); - - wins_ip=*interpret_addr2(ip_str); - - /* Allocate the space for the ip_list. */ - if((ip_list = (struct in_addr *)talloc(mem_ctx, num_ips * sizeof(struct in_addr))) == NULL) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("initialise_wins: talloc fail !\n")); - return; - } - - for (i = 0; i < num_ips; i++) { - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str); - ip_list[i] = *interpret_addr2(ip_str); - } - - SAFE_FREE(dbuf.dptr); - - /* add all entries that have 60 seconds or more to live */ - if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { - if(ttl != PERMANENT_TTL) - ttl -= time_now; - - DEBUG( 4, ("send_entry_request: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - - /* add the record to the list to send */ - version=((SMB_BIG_UINT)high)<<32 | low; - - if (wins_owner->min_version<=version && wins_owner->max_version>=version && - wins_owner->address.s_addr==wins_ip.s_addr) { - if(!add_record_to_winsname(&r->rep.se_rp.wins_name, &max_names, name, type, wins_flags, version, ip_list, num_ips)) - return; - max_names++; - } - - } else { - DEBUG(4, ("send_entry_request: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } - } - - tdb_close(tdb); - - DEBUG(4,("send_entry_request, sending %d records\n", max_names)); - fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE); - r->rep.msg_type=MESSAGE_REP_SEND_ENTRIES_REPLY; /* reply */ - r->rep.se_rp.max_names=max_names; -} - - -/**************************************************************************** -. -****************************************************************************/ -static void update_notify_request(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - int i,j,k,l; - UPDATE_NOTIFY_REQUEST *u; - int s_ctx=get_server_assoc(q->header.assoc_ctx); - - if (s_ctx==0) { - DEBUG(4, ("update_notify_request: request for a partner not in our table\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - u=&q->rep.un_rq; - - /* check if we already have the range of records */ - - DEBUG(5,("update_notify_request: wins server: %s offered this list of %d records:\n", - inet_ntoa(u->initiating_wins_server), u->partner_count)); - - get_our_last_id(&global_wins_table[0][0]); - - for (i=0; i<partner_count; i++) { - if (global_wins_table[0][i].address.s_addr==u->initiating_wins_server.s_addr) { - DEBUG(5,("update_notify_request: found initiator at index %d\n", i)); - break; - } - } - - /* - * some explanation is required, before someone say it's crap. - * - * let's take an example, we have 2 wins partners, we already now - * that our max id is 10, partner 1 ID is 20 and partner 2 ID is 30 - * the array looks like: - * - * 0 1 2 - * 0 10 20 30 - * 1 - * 2 - * - * we receive an update from partner 2 saying he has: 1:15, 2:40, 3:50 - * we must enlarge the array to add partner 3, it will look like: - * - * 0 1 2 3 - * 0 10 20 30 - * 1 - * 2 15 40 50 - * - * now we know, we should pull from partner 2, the records 30->40 of 2 and 0->50 of 3. - * once the pull will be over, our table will look like: - * - * 0 1 2 3 - * 0 10 20 40 50 - * 1 - * 2 15 40 50 - * - * - */ - - for (j=0; j<u->partner_count;j++) { - /* - * search if we already have this entry or if it's a new one - * it can be a new one in case of propagation - */ - - for (k=0; global_wins_table[0][k].address.s_addr!=0 && - global_wins_table[0][k].address.s_addr!=u->wins_owner[j].address.s_addr; k++); - - global_wins_table[i][k].address.s_addr=u->wins_owner[j].address.s_addr; - global_wins_table[i][k].max_version=u->wins_owner[j].max_version; - global_wins_table[i][k].min_version=u->wins_owner[j].min_version; - global_wins_table[i][k].type=u->wins_owner[j].type; - - /* - * in case it's a new one, rewrite the address for all the partner - * to reserve the slot. - */ - - for(l=0; l<partner_count; l++) - global_wins_table[l][k].address.s_addr=u->wins_owner[j].address.s_addr; - } - - dump_global_table(); - - stop_packet(q, r, STOP_REASON_USER_REASON); -} - -/**************************************************************************** -. -****************************************************************************/ -static void send_entry_reply(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - int i,j,k; - struct in_addr partner, server; - pid_t pid; - int s_ctx=get_server_assoc(q->header.assoc_ctx); - WINS_RECORD record; - - if (s_ctx==0) { - DEBUG(1, ("send_entry_reply: request for a partner not in our table\n")); - stop_packet(q, r, STOP_REASON_USER_REASON); - return; - } - - DEBUG(5,("send_entry_reply:got %d new records\n", q->rep.se_rp.max_names)); - - /* we got records from a wins partner but that can be from another wins server */ - /* hopefully we track that */ - - /* and the only doc available from MS is wrong ! */ - - get_server_assoc_table(q->header.assoc_ctx, &partner, &server); - - for (j=0; global_wins_table[0][j].address.s_addr!=0; j++) { - if (global_wins_table[0][j].address.s_addr==server.s_addr) { - DEBUG(5,("send_entry_reply: found server at index %d\n", j)); - break; - } - } - - pid = pidfile_pid("nmbd"); - if (pid == 0) { - DEBUG(0,("send_entry_reply: Can't find pid for nmbd\n")); - return; - } - - for (k=0; k<q->rep.se_rp.max_names; k++) { - DEBUG(5,("send_entry_reply: %s<%02x> %d\n", q->rep.se_rp.wins_name[k].name, q->rep.se_rp.wins_name[k].type, - (int)q->rep.se_rp.wins_name[k].id)); - - safe_strcpy(record.name, q->rep.se_rp.wins_name[k].name, 16); - record.type=q->rep.se_rp.wins_name[k].type; - record.id=q->rep.se_rp.wins_name[k].id; - record.wins_flags=q->rep.se_rp.wins_name[k].name_flag&0x00ff; - record.num_ips=q->rep.se_rp.wins_name[k].num_ip; - - record.wins_ip.s_addr=server.s_addr; - - if (record.num_ips==1) - record.ip[0]=q->rep.se_rp.wins_name[k].owner; - else - for (i=0; i<record.num_ips; i++) - record.ip[i]=q->rep.se_rp.wins_name[k].others[i]; - - record.nb_flags=0; - - if (record.wins_flags&WINS_NGROUP || record.wins_flags&WINS_SGROUP) - record.nb_flags|=NB_GROUP; - - if (record.wins_flags&WINS_ACTIVE) - record.nb_flags|=NB_ACTIVE; - - record.nb_flags|=record.wins_flags&WINS_HNODE; - - message_send_pid(pid, MSG_WINS_NEW_ENTRY, &record, sizeof(record), False); - - } - - dump_global_table(); - - /* - * we got some entries, - * ask the partner to send us the map table again - * to get the other servers entries. - * - * we're getting the map table 1 time more than really - * required. We could remove that call, but that - * would complexify the code. I prefer this trade-of. - */ - fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE); - - r->rep.msg_type=MESSAGE_REP_ADD_VERSION_REQUEST; -} - -/**************************************************************************** -decode the replication message and reply. -****************************************************************************/ -static void replicate(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - switch (q->rep.msg_type) { - case 0: - /* add version number map table request */ - send_version_number_map_table(q, r); - break; - case 1: - receive_version_number_map_table(q, r); - break; - case 2: - /* send entry request */ - send_entry_request(q, r); - break; - case 3: - /* send entry reply */ - send_entry_reply(q, r); - break; - case 4: - /* update notification request */ - update_notify_request(q, r); - break; - } -} - -/**************************************************************************** -do a switch on the message type, and return the response size -****************************************************************************/ -static BOOL switch_message(GENERIC_PACKET *q, GENERIC_PACKET *r) -{ - switch (q->header.mess_type) { - case 0: - /* Start association type */ - start_assoc_process(q, r); - return True; - break; - case 1: - /* start association reply */ - start_assoc_reply(q, r); - return True; - break; - case 2: - /* stop association message */ - return False; - break; - case 3: - /* replication message */ - replicate(q, r); - return True; - break; - } - - return False; -} - - -/**************************************************************************** - construct a reply to the incoming packet -****************************************************************************/ -void construct_reply(struct wins_packet_struct *p) -{ - GENERIC_PACKET r; - struct BUFFER buffer; - - buffer.buffer=NULL; - buffer.offset=0; - buffer.length=0; - - DEBUG(5,("dump: received packet\n")); - dump_generic_packet(p->packet); - - /* Verify if the request we got is from a listed partner */ - if (!check_partner(p->packet->header.assoc_ctx)) { - fstring peer; - struct in_addr addr; - int i; - fstrcpy(peer,get_socket_addr(p->fd)); - addr=*interpret_addr2(peer); - - for (i=1; i<partner_count; i++) - if (ip_equal(addr, global_wins_table[0][i].address)) - break; - - if (i==partner_count) { - DEBUG(1,("construct_reply: got a request from a non peer machine: %s\n", peer)); - stop_packet(p->packet, &r, STOP_REASON_AUTH_FAILED); - p->stop_packet=True; - encode_generic_packet(&buffer, &r); - if (!send_smb(p->fd, buffer.buffer)) - exit_server("process_smb: send_smb failed."); - return; - } - } - - if (switch_message(p->packet, &r)) { - encode_generic_packet(&buffer, &r); - DEBUG(5,("dump: sending packet\n")); - dump_generic_packet(&r); - - if(buffer.offset > 0) { - if (!send_smb(p->fd, buffer.buffer)) - exit_server("process_smb: send_smb failed."); - } - } - - /* if we got a stop assoc or if we send a stop assoc, close the fd after */ - if (p->packet->header.mess_type==MESSAGE_TYPE_STOP_ASSOC || - r.header.mess_type==MESSAGE_TYPE_STOP_ASSOC) { - remove_partner(p->packet->header.assoc_ctx); - p->stop_packet=True; - } -} - -/**************************************************************************** - contact periodically our wins partner to do a pull replication -****************************************************************************/ -void run_pull_replication(time_t t) -{ - /* we pull every 30 minutes to query about new records*/ - int i, s; - struct BUFFER buffer; - GENERIC_PACKET p; - - buffer.buffer=NULL; - buffer.offset=0; - buffer.length=0; - - for (i=1; i<partner_count; i++) { - if (global_wins_table[0][i].last_pull < t) { - global_wins_table[0][i].last_pull=t+30*60; /* next in 30 minutes */ - - /* contact the wins server */ - p.header.mess_type=MESSAGE_TYPE_START_ASSOC_REQUEST; - p.header.opcode=OPCODE_NON_NBT; - p.header.assoc_ctx=0; - p.sa_rq.assoc_ctx=(int)t; - p.sa_rq.min_ver=1; - p.sa_rq.maj_ver=1; - - DEBUG(3,("run_pull_replication: contacting wins server %s.\n", inet_ntoa(global_wins_table[0][i].address))); - encode_generic_packet(&buffer, &p); - dump_generic_packet(&p); - - /* send the packet to the server and add the descriptor to receive answers */ - s=open_socket_out(SOCK_STREAM, &global_wins_table[0][i].address, 42, LONG_CONNECT_TIMEOUT); - if (s==-1) { - DEBUG(0,("run_pull_replication: can't contact wins server %s.\n", inet_ntoa(global_wins_table[0][i].address))); - return; - } - - if(buffer.offset > 0) { - if (!send_smb(s, buffer.buffer)) - exit_server("run_pull_replication: send_smb failed."); - } - - add_fd_to_sock_array(s); - FD_SET(s, listen_set); - - /* add ourself as a client */ - add_partner((int)t, 0, True, False); - } - } -} - -/**************************************************************************** - contact periodically our wins partner to do a push replication -****************************************************************************/ -void run_push_replication(time_t t) -{ - /* we push every 30 minutes or 25 new entries */ - int i, s; - struct BUFFER buffer; - GENERIC_PACKET p; - - buffer.buffer=NULL; - buffer.offset=0; - buffer.length=0; - - for (i=1; i<partner_count; i++) { - if (global_wins_table[0][i].last_pull < t) { - global_wins_table[0][i].last_pull=t+30*60; /* next in 30 minutes */ - - /* contact the wins server */ - p.header.mess_type=MESSAGE_TYPE_START_ASSOC_REQUEST; - p.header.opcode=OPCODE_NON_NBT; - p.header.assoc_ctx=0; - p.sa_rq.assoc_ctx=(int)t; - p.sa_rq.min_ver=1; - p.sa_rq.maj_ver=1; - - DEBUG(3,("run_push_replication: contacting wins server %s.\n", inet_ntoa(global_wins_table[0][i].address))); - encode_generic_packet(&buffer, &p); - dump_generic_packet(&p); - - /* send the packet to the server and add the descriptor to receive answers */ - s=open_socket_out(SOCK_STREAM, &global_wins_table[0][i].address, 42, LONG_CONNECT_TIMEOUT); - if (s==-1) { - DEBUG(0,("run_push_replication: can't contact wins server %s.\n", inet_ntoa(global_wins_table[0][i].address))); - return; - } - - if(buffer.offset > 0) { - if (!send_smb(s, buffer.buffer)) - exit_server("run_push_replication: send_smb failed."); - } - - add_fd_to_sock_array(s); - FD_SET(s, listen_set); - - /* add ourself as a client */ - add_partner((int)t, 0, False, True); - } - } -} - diff --git a/source4/wrepld/server.c b/source4/wrepld/server.c deleted file mode 100644 index f49596dc41..0000000000 --- a/source4/wrepld/server.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Main SMB server routines - Copyright (C) Jean François Micouleau 1998-2002. - - 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 "wins_repl.h" - -extern WINS_OWNER *global_wins_table; -extern int partner_count; - -extern fd_set *listen_set; -extern int listen_number; -extern int *sock_array; - -extern TALLOC_CTX *mem_ctx; - -int wins_port = 42; - -/**************************************************************************** - when exiting, take the whole family -****************************************************************************/ -static void *dflt_sig(void) -{ - exit_server("caught signal"); - return NULL; -} - -/**************************************************************************** - reload the services file - **************************************************************************/ -BOOL reload_services(BOOL test) -{ - BOOL ret; - - if (lp_loaded()) { - pstring fname; - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); - test = False; - } - } - - reopen_logs(); - - if (test && !lp_file_list_changed()) - return(True); - - ret = lp_load(dyn_CONFIGFILE,False,False,True); - - - /* perhaps the config filename is now set */ - if (!test) - reload_services(True); - - reopen_logs(); - - load_interfaces(); - - return(ret); -} - -/**************************************************************************** - Catch a sighup. -****************************************************************************/ - -VOLATILE sig_atomic_t reload_after_sighup = False; - -static void sig_hup(int sig) -{ - BlockSignals(True,SIGHUP); - DEBUG(0,("Got SIGHUP\n")); - - sys_select_signal(); - reload_after_sighup = True; - BlockSignals(False,SIGHUP); -} - -#if DUMP_CORE -/******************************************************************* -prepare to dump a core file - carefully! -********************************************************************/ -static BOOL dump_core(void) -{ - char *p; - pstring dname; - pstrcpy(dname,lp_logfile()); - if ((p=strrchr_m(dname,'/'))) *p=0; - pstrcat(dname,"/corefiles"); - mkdir(dname,0700); - sys_chown(dname,getuid(),getgid()); - chmod(dname,0700); - if (chdir(dname)) return(False); - umask(~(0700)); - -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit(RLIMIT_CORE, &rlp); - rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); - setrlimit(RLIMIT_CORE, &rlp); - getrlimit(RLIMIT_CORE, &rlp); - DEBUG(3,("Core limits now %d %d\n", - (int)rlp.rlim_cur,(int)rlp.rlim_max)); - } -#endif -#endif - - - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return(True); -} -#endif - -/**************************************************************************** -exit the server -****************************************************************************/ -void exit_server(const char *reason) -{ - static int firsttime=1; - - if (!firsttime) - exit(0); - firsttime = 0; - - DEBUG(2,("Closing connections\n")); - - if (!reason) { - int oldlevel = DEBUGLEVEL; - DEBUGLEVEL = 10; - DEBUGLEVEL = oldlevel; - DEBUG(0,("===============================================================\n")); -#if DUMP_CORE - if (dump_core()) return; -#endif - } - - DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); - exit(0); -} - -/**************************************************************************** - Usage of the program. -****************************************************************************/ - -static void usage(char *pname) -{ - - d_printf("Usage: %s [-DFSaioPh?V] [-d debuglevel] [-l log basename] [-p port]\n", pname); - d_printf(" [-O socket options] [-s services file]\n"); - d_printf("\t-D Become a daemon (default)\n"); - d_printf("\t-F Run daemon in foreground (for daemontools, etc)\n"); - d_printf("\t-S Log to stdout\n"); - d_printf("\t-a Append to log file (default)\n"); - d_printf("\t-i Run interactive (not a daemon)\n" ); - d_printf("\t-o Overwrite log file, don't append\n"); - d_printf("\t-h Print usage\n"); - d_printf("\t-? Print usage\n"); - d_printf("\t-V Print version\n"); - d_printf("\t-d debuglevel Set the debuglevel\n"); - d_printf("\t-l log basename. Basename for log/debug files\n"); - d_printf("\t-p port Listen on the specified port\n"); - d_printf("\t-O socket options Socket options\n"); - d_printf("\t-s services file. Filename of services file\n"); - d_printf("\n"); -} - -/**************************************************************************** - Create an fd_set containing all the sockets in the subnet structures, - plus the broadcast sockets. -***************************************************************************/ - -static BOOL create_listen_fdset(void) -{ - int i; - int num_interfaces = iface_count(); - int s; - - listen_set = (fd_set *)malloc(sizeof(fd_set)); - if(listen_set == NULL) { - DEBUG(0,("create_listen_fdset: malloc fail !\n")); - return True; - } - -#ifdef HAVE_ATEXIT - { - static int atexit_set; - if(atexit_set == 0) { - atexit_set=1; - } - } -#endif - - FD_ZERO(listen_set); - - if(lp_interfaces() && lp_bind_interfaces_only()) { - /* We have been given an interfaces line, and been - told to only bind to those interfaces. Create a - socket per interface and bind to only these. - */ - - if(num_interfaces > FD_SETSIZE) { - DEBUG(0,("create_listen_fdset: Too many interfaces specified to bind to. Number was %d max can be %d\n", num_interfaces, FD_SETSIZE)); - return False; - } - - /* Now open a listen socket for each of the interfaces. */ - for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) { - DEBUG(0,("create_listen_fdset: interface %d has NULL IP address !\n", i)); - continue; - } - s = open_socket_in(SOCK_STREAM, wins_port, 0, ifip->s_addr, True); - if(s == -1) - return False; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,lp_socket_options()); - - if (listen(s, 5) == -1) { - DEBUG(5,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - add_fd_to_sock_array(s); - FD_SET(s, listen_set); - } - } else { - /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - num_interfaces = 1; - - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, wins_port, 0, interpret_addr(lp_socket_address()),True); - if (s == -1) - return(False); - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s, lp_socket_options()); - - if (listen(s, 5) == -1) { - DEBUG(0,("create_listen_fdset: listen: %s\n", strerror(errno))); - close(s); - return False; - } - - add_fd_to_sock_array(s); - FD_SET(s, listen_set); - } - - return True; -} - -/******************************************************************* - read a packet from a socket and parse it, returning a packet ready - to be used or put on the queue. This assumes a UDP socket - ******************************************************************/ -static struct wins_packet_struct *read_wins_packet(int fd, int timeout) -{ - struct wins_packet_struct *p; - GENERIC_PACKET *q; - struct BUFFER inbuf; - ssize_t len=0; - size_t total=0; - ssize_t ret; - BOOL ok = False; - - inbuf.buffer=NULL; - inbuf.length=0; - inbuf.offset=0; - - if(!grow_buffer(&inbuf, 4)) - return NULL; - - ok = (read(fd, inbuf.buffer,4) == 4); - if (!ok) - return NULL; - len = smb_len(inbuf.buffer); - - if (len<=0) - return NULL; - - if(!grow_buffer(&inbuf, len)) - return NULL; - - while (total < len) { - ret = read(fd, inbuf.buffer + total + 4, len - total); - if (ret == 0) { - DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(len - total), strerror(errno) )); - return NULL; - } - if (ret == -1) { - DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(len - total), strerror(errno) )); - return NULL; - } - total += ret; - } - - q = (GENERIC_PACKET *)talloc(mem_ctx, sizeof(GENERIC_PACKET)); - p = (struct wins_packet_struct *)talloc(mem_ctx, sizeof(*p)); - if (q==NULL || p==NULL) - return NULL; - - decode_generic_packet(&inbuf, q); - - q->fd=fd; - - p->next = NULL; - p->prev = NULL; - p->stop_packet = False; - p->timestamp = time(NULL); - p->fd = fd; - p->packet=q; - - return p; -} - -static struct wins_packet_struct *packet_queue = NULL; - -/******************************************************************* - Queue a packet into a packet queue -******************************************************************/ -static void queue_packet(struct wins_packet_struct *packet) -{ - struct wins_packet_struct *p; - - if (!packet_queue) { - packet->prev = NULL; - packet->next = NULL; - packet_queue = packet; - return; - } - - /* find the bottom */ - for (p=packet_queue;p->next;p=p->next) - ; - - p->next = packet; - packet->next = NULL; - packet->prev = p; -} - -/**************************************************************************** - Listens for NMB or DGRAM packets, and queues them. - return True if the socket is dead -***************************************************************************/ -static BOOL listen_for_wins_packets(void) -{ - int num_interfaces = iface_count(); - fd_set fds; - int i, num, s, new_s; - struct timeval timeout; - - if(listen_set == NULL) { - if(!create_listen_fdset()) { - DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); - return True; - } - } - - memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); - - timeout.tv_sec = NMBD_SELECT_LOOP; - timeout.tv_usec = 0; - - /* Prepare for the select - allow certain signals. */ - - BlockSignals(False, SIGTERM); - - num = sys_select(FD_SETSIZE, &fds, NULL, NULL, &timeout); - - /* We can only take signals when we are in the select - block them again here. */ - - BlockSignals(True, SIGTERM); - - if(num == -1) - return False; - - for (; num > 0; num--) { - s = -1; - /* check the sockets we are only listening on, waiting to accept */ - for (i=0; i<num_interfaces; i++) { - struct sockaddr addr; - socklen_t in_addrlen = sizeof(addr); - - if(FD_ISSET(sock_array[i], &fds)) { - s = sock_array[i]; - /* Clear this so we don't look at it again. */ - FD_CLR(sock_array[i], &fds); - - /* accept and add the new socket to the listen set */ - new_s=accept(s, &addr, &in_addrlen); - - if (new_s < 0) - continue; - - DEBUG(5,("listen_for_wins_packets: new connection, old: %d, new : %d\n", s, new_s)); - - set_socket_options(new_s, "SO_KEEPALIVE"); - set_socket_options(new_s, lp_socket_options()); - FD_SET(new_s, listen_set); - add_fd_to_sock_array(new_s); - } - } - - /* - * check for the sockets we are waiting data from - * either client sending datas - * or reply to our requests - */ - for (i=num_interfaces; i<listen_number; i++) { - if(FD_ISSET(sock_array[i], &fds)) { - struct wins_packet_struct *packet = read_wins_packet(sock_array[i], timeout.tv_sec); - if (packet) { - packet->fd = sock_array[i]; - queue_packet(packet); - } - DEBUG(2,("listen_for_wins_packets: some data on fd %d\n", sock_array[i])); - FD_CLR(sock_array[i], &fds); - break; - } - - } - - } - - return False; -} - - -/******************************************************************* - Run elements off the packet queue till its empty -******************************************************************/ - -static void run_wins_packet_queue(void) -{ - struct wins_packet_struct *p; - - while ((p = packet_queue)) { - packet_queue = p->next; - if (packet_queue) - packet_queue->prev = NULL; - p->next = p->prev = NULL; - - construct_reply(p); - - /* if it was a stop assoc, close the connection */ - if (p->stop_packet) { - FD_CLR(p->fd, listen_set); - remove_fd_from_sock_array(p->fd); - close(p->fd); - } - } -} - -/**************************************************************************** ** - The main select loop. - **************************************************************************** */ -static void process(void) -{ - - while( True ) { - time_t t = time(NULL); - - /* check for internal messages */ - message_dispatch(); - - if(listen_for_wins_packets()) - return; - - run_wins_packet_queue(); - - run_pull_replication(t); - - run_push_replication(t); - - /* - * Reload the services file if we got a sighup. - */ - - if(reload_after_sighup) { - reload_services( True ); - reopen_logs(); - reload_after_sighup = False; - } - - /* free temp memory */ - talloc_destroy_pool(mem_ctx); - - /* free up temp memory */ - lp_talloc_free(); - } -} /* process */ - -/**************************************************************************** - main program -****************************************************************************/ - int main(int argc,char *argv[]) -{ - extern char *optarg; - /* shall I run as a daemon */ - BOOL is_daemon = False; - BOOL interactive = False; - BOOL specified_logfile = False; - BOOL Fork = True; - BOOL log_stdout = False; - int opt; - pstring logfile; - -#ifdef HAVE_SET_AUTH_PARAMETERS - set_auth_parameters(argc,argv); -#endif - - /* this is for people who can't start the program correctly */ - while (argc > 1 && (*argv[1] != '-')) { - argv++; - argc--; - } - - while ( EOF != (opt = getopt(argc, argv, "FSO:l:s:d:Dp:h?Vaiof:")) ) - switch (opt) { - case 'F': - Fork = False; - break; - case 'S': - log_stdout = True; - break; - case 'O': - lp_set_cmdline("socket options", optarg); - break; - - case 's': - pstrcpy(dyn_CONFIGFILE,optarg); - break; - - case 'l': - specified_logfile = True; - slprintf(logfile, sizeof(logfile)-1, "%s/log.wrepld", optarg); - lp_set_logfile(logfile); - break; - - case 'i': - interactive = True; - Fork = False; - log_stdout = True; - break; - - case 'D': - is_daemon = True; - break; - - case 'd': - if (*optarg == 'A') - DEBUGLEVEL = 10000; - else - DEBUGLEVEL = atoi(optarg); - break; - - case 'p': - wins_port = atoi(optarg); - break; - - case 'h': - case '?': - usage(argv[0]); - exit(0); - break; - - case 'V': - d_printf("Version %s\n",VERSION); - exit(0); - break; - default: - DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - usage(argv[0]); - exit(1); - } - if (log_stdout && Fork) { - d_printf("Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"); - usage(argv[0]); - exit(1); - } - -#ifdef HAVE_SETLUID - /* needed for SecureWare on SCO */ - setluid(0); -#endif - - sec_init(); - - load_case_tables(); - - if(!specified_logfile) { - slprintf(logfile, sizeof(logfile)-1, "%s/log.wrepld", - dyn_LOGFILEBASE); - lp_set_logfile(logfile); - } - - set_remote_machine_name("wrepld"); - - setup_logging(argv[0],log_stdout?DEBUG_STDOUT:DEBUG_FILE); - - /* we want to re-seed early to prevent time delays causing - client problems at a later date. (tridge) */ - generate_random_buffer(NULL, 0, False); - - /* make absolutely sure we run as root - to handle cases where people - are crazy enough to have it setuid */ - - gain_root_privilege(); - gain_root_group_privilege(); - - fault_setup((void (*)(void *))exit_server); - CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig); - - /* we are never interested in SIGPIPE */ - BlockSignals(True,SIGPIPE); - -#if defined(SIGFPE) - /* we are never interested in SIGFPE */ - BlockSignals(True,SIGFPE); -#endif - -#if defined(SIGUSR2) - /* We are no longer interested in USR2 */ - BlockSignals(True,SIGUSR2); -#endif - - /* POSIX demands that signals are inherited. If the invoking process has - * these signals masked, we will have problems, as we won't recieve them. */ - BlockSignals(False, SIGHUP); - BlockSignals(False, SIGUSR1); - - /* we want total control over the permissions on created files, - so set our umask to 0 */ - umask(0); - - reopen_logs(); - - DEBUG(1,( "wrepld version %s started.\n", VERSION)); - DEBUGADD(1,( "Copyright Andrew Tridgell and the Samba Team 1992-2002\n")); - - DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", - (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); - - if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { - DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); - exit(1); - } - - /* - * Do this before reload_services. - */ - - if (!reload_services(False)) - return(-1); - - if (!init_names()) - return -1; - -#ifdef WITH_PROFILE - if (!profile_setup(False)) { - DEBUG(0,("ERROR: failed to setup profiling\n")); - return -1; - } -#endif - - CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); - - DEBUG(3,( "loaded services\n")); - - if (!is_daemon && !is_a_socket(0)) { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } - - if (is_daemon && !interactive) { - DEBUG( 3, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork); - } - -#if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (interactive) - setpgid( (pid_t)0, (pid_t)0); -#endif - - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } - - if (is_daemon) { - pidfile_create("wrepld"); - } - - if (!message_init()) { - exit(1); - } - - /* Initialise the memory context */ - mem_ctx=talloc_init("wins repl talloc ctx"); - - /* initialise the global partners table */ - partner_count=init_wins_partner_table(); - - /* We can only take signals in the select. */ - BlockSignals( True, SIGTERM ); - - process(); - - exit_server("normal exit"); - return(0); -} diff --git a/source4/wrepld/socket.c b/source4/wrepld/socket.c deleted file mode 100644 index 3d759f0ab8..0000000000 --- a/source4/wrepld/socket.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - Unix SMB/CIFS implementation. - process incoming packets - main loop - Copyright (C) Jean François Micouleau 1998-2002. - - 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 "wins_repl.h" - -fd_set *listen_set = NULL; -int listen_number = 0; -int *sock_array = NULL; - -/******************************************************************* - Add an fd from the sock_array -******************************************************************/ -void add_fd_to_sock_array(int fd) -{ - int *temp_sock=NULL; - - temp_sock=(int *)Realloc(sock_array, (listen_number+1)*sizeof(int)); - if (temp_sock==NULL) - return; - - sock_array=temp_sock; - sock_array[listen_number]=fd; - listen_number++; -} - - -/******************************************************************* - Remove an fd from the sock_array -******************************************************************/ -void remove_fd_from_sock_array(int fd) -{ - int i,j; - - for (i=0; sock_array[i]!=fd && i<listen_number; i++) - ; - - if (i==listen_number) { - DEBUG(0,("remove_fd_from_sock_array: unknown fd: %d\n", fd)); - return; - } - - if (i==listen_number-1) { - sock_array=(int *)Realloc(sock_array, --listen_number*sizeof(int)); - return; - } - - for (j=i; j<listen_number-1; j++) - sock_array[j]=sock_array[j+1]; - - sock_array=(int *)Realloc(sock_array, --listen_number*sizeof(int)); -} diff --git a/source4/wrepld/wins_repl.h b/source4/wrepld/wins_repl.h deleted file mode 100644 index 7aa7fa6a9e..0000000000 --- a/source4/wrepld/wins_repl.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Jean François Micouleau 1998-2002. - * - * 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. - */ - -#define OPCODE_NON_NBT 0x00007800 - -/* the messages */ -#define MESSAGE_TYPE_START_ASSOC_REQUEST 0 -#define MESSAGE_TYPE_START_ASSOC_REPLY 1 -#define MESSAGE_TYPE_STOP_ASSOC 2 -#define MESSAGE_TYPE_REPLICATE 3 - -/* the replication sub-message */ -#define MESSAGE_REP_ADD_VERSION_REQUEST 0 -#define MESSAGE_REP_ADD_VERSION_REPLY 1 -#define MESSAGE_REP_SEND_ENTRIES_REQUEST 2 -#define MESSAGE_REP_SEND_ENTRIES_REPLY 3 -#define MESSAGE_REP_UPDATE_NOTIFY_REQUEST 4 - -/* stop reasons */ -#define STOP_REASON_USER_REASON 0 -#define STOP_REASON_AUTH_FAILED 1 -#define STOP_REASON_INCOMPLETE_VERSION 2 -#define STOP_REASON_BUG_CHECK 3 -#define STOP_REASON_MESSAGE_ERROR 4 - - -typedef struct _WINS_OWNER { - struct in_addr address; - SMB_BIG_UINT max_version; - SMB_BIG_UINT min_version; - int type; - time_t last_pull; - time_t last_push; -} WINS_OWNER; - -typedef struct _WINS_NAME { - int name_len; /* always 0x11 */ - char name[16]; - char type; - int empty; - int name_flag; - int group_flag; - SMB_BIG_UINT id; - int num_ip; - struct in_addr owner; - struct in_addr *others; - int foo; /* 0xffffff */ -} WINS_NAME; - -typedef struct _WINS_PARTNERS -{ - int client_assoc; - int server_assoc; - BOOL pull_partner; - BOOL push_partner; - struct in_addr partner_server; - struct in_addr other_server; -} WINS_PARTNER; - -typedef struct _generic_header{ - int data_size; - int opcode; - int assoc_ctx; - int mess_type; -} generic_header; - -typedef struct _START_ASSOC_REQUEST { - int assoc_ctx; - int min_ver; - int maj_ver; -} START_ASSOC_REQUEST; - -typedef struct _START_ASSOC_REPLY { - int assoc_ctx; - int min_ver; - int maj_ver; -} START_ASSOC_REPLY; - -typedef struct _STOP_ASSOC { - int reason; -} STOP_ASSOC; - -typedef struct _AVMT_REP { - int partner_count; - WINS_OWNER *wins_owner; - struct in_addr initiating_wins_server; -} AVMT_REP; - -typedef struct _SEND_ENTRIES_REQUEST { - WINS_OWNER wins_owner; -} SEND_ENTRIES_REQUEST; - -typedef struct _SEND_ENTRIES_REPLY { - int max_names; - WINS_NAME *wins_name; -} SEND_ENTRIES_REPLY; - -typedef struct _UPDATE_NOTIFY_REQUEST { - int partner_count; - WINS_OWNER *wins_owner; - struct in_addr initiating_wins_server; -} UPDATE_NOTIFY_REQUEST; - -typedef struct _REPLICATE { - int msg_type; - - AVMT_REP avmt_rep; - SEND_ENTRIES_REQUEST se_rq; - SEND_ENTRIES_REPLY se_rp; - UPDATE_NOTIFY_REQUEST un_rq; -} REPLICATE; - - -typedef struct _GENERIC_PACKET { - int fd; - - generic_header header; - - START_ASSOC_REQUEST sa_rq; - START_ASSOC_REPLY sa_rp; - STOP_ASSOC so; - REPLICATE rep; -} GENERIC_PACKET; - -struct wins_packet_struct -{ - struct wins_packet_struct *next; - struct wins_packet_struct *prev; - BOOL stop_packet; - int fd; - time_t timestamp; - GENERIC_PACKET *packet; -}; - -struct BUFFER { - char *buffer; - int offset; - int length; -}; - - - |