From 3e074dcd9664edc32d1d4947179ce90d5c4ae801 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 1997 19:44:48 +0000 Subject: Updated code on 1.9.17 branch to add bug fixes. This is *NOT* the same branch as the main (ie. 1.9.18) branch. Jeremy (jallison@whistle.com) --- source/client/clientutil.c | 6 ++++ source/client/clitar.c | 3 +- source/include/includes.h | 4 +++ source/include/proto.h | 26 ++++++++++------ source/include/smb.h | 2 ++ source/include/version.h | 2 +- source/lib/charset.c | 2 +- source/lib/util.c | 47 ++++++++++++++++++++++++++-- source/nameannounce.c | 2 +- source/namepacket.c | 15 ++++++--- source/nameresp.c | 14 ++++----- source/nameserv.c | 6 ++-- source/nameservreply.c | 78 +++++++++++++++++++++++++++------------------- source/nmbsync.c | 2 ++ source/param/loadparm.c | 19 +++++++++-- source/printing/printing.c | 24 ++++++++++++-- source/script/mkproto.awk | 2 +- source/smbd/ipc.c | 25 +++++++-------- source/smbd/mangle.c | 2 +- source/smbd/password.c | 20 ++++++++++-- source/smbd/reply.c | 41 +++++++++++++++++++++--- source/smbd/server.c | 68 +++++++++++++++++++++++++++++++--------- source/smbd/trans2.c | 10 ++---- 23 files changed, 308 insertions(+), 112 deletions(-) diff --git a/source/client/clientutil.c b/source/client/clientutil.c index 000cbba1a78..b4f0849c5fe 100644 --- a/source/client/clientutil.c +++ b/source/client/clientutil.c @@ -428,6 +428,12 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu else pass = (char *)getpass("Password: "); + if(pass == NULL) + { + DEBUG(0, ("cli_send_login : no password available - logon failed.\n")); + return False; + } + if (Protocol >= PROTOCOL_LANMAN1 && use_setup) { fstring pword; diff --git a/source/client/clitar.c b/source/client/clitar.c index f70e639e905..d5bca8c5bbb 100644 --- a/source/client/clitar.c +++ b/source/client/clitar.c @@ -376,8 +376,7 @@ Compare two strings in a slash insensitive way, allowing s1 to match s2 if s1 is an "initial" string (up to directory marker). Thus, if s2 is a file in any subdirectory of s1, declare a match. ***************************************************************************/ -static -int strslashcmp(char *s1, char *s2) +static int strslashcmp(char *s1, char *s2) { char *s1_0=s1; diff --git a/source/include/includes.h b/source/include/includes.h index 15a5e74e469..a63f8f8597c 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -308,7 +308,9 @@ extern int innetgr (const char *, const char *, const char *, const char *); #define USE_STATVFS #define USE_GETCWD #define USE_SETSID +#ifndef REPLACE_GETPASS #define REPLACE_GETPASS +#endif /* REPLACE_GETPASS */ #define USE_SIGPROCMASK #endif @@ -459,7 +461,9 @@ char *mktemp(char *); /* No standard include */ #define NO_FSYNC #define USE_GETCWD #define USE_SETSID +#ifndef REPLACE_GETPASS #define REPLACE_GETPASS +#endif /* REPLACE_GETPASS */ #define NO_GETRLIMIT #endif /* CLIX */ diff --git a/source/include/proto.h b/source/include/proto.h index 9f05e5bbffd..01afb7cad95 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -146,6 +146,7 @@ char *lp_wins_server(void); char *lp_interfaces(void); char *lp_socket_address(void); char *lp_nis_home_map_name(void); +char *lp_announce_version(void); char *lp_netbios_aliases(void); BOOL lp_dns_proxy(void); BOOL lp_wins_support(void); @@ -189,6 +190,7 @@ int lp_maxdisksize(void); int lp_lpqcachetime(void); int lp_syslog(void); int lp_client_code_page(void); +int lp_announce_as(void); char *lp_preexec(int ); char *lp_postexec(int ); char *lp_rootpreexec(int ); @@ -268,10 +270,10 @@ BOOL lp_load(char *pszFname,BOOL global_only); int lp_numservices(void); void lp_dump(void); int lp_servicenumber(char *pszServiceName); +char *volume_label(int snum); int lp_default_server_announce(void); int lp_major_announce_version(void); int lp_minor_announce_version(void); -char *volume_label(int snum); /*The following definitions come from locking.c */ @@ -460,7 +462,9 @@ void initiate_netbios_packet(uint16 *id, int nb_flags,BOOL bcast,BOOL recurse, struct in_addr to_ip); void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, + int rcode, int rcv_code, int opcode, + BOOL recursion_available, + BOOL recursion_desired, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, char *data,int len); void queue_packet(struct packet_struct *packet); @@ -486,7 +490,6 @@ struct response_record *queue_netbios_pkt_wins( int fd,int quest_type,enum state_type state, char *name,int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip); struct response_record *queue_netbios_packet(struct subnet_record *d, int fd,int quest_type,enum state_type state,char *name, @@ -613,6 +616,8 @@ int get_printqueue(int snum,int cnum,print_queue_struct **queue, print_status_struct *status); void del_printqueue(int cnum,int snum,int jobid); void status_printjob(int cnum,int snum,int jobid,int status); +int printjob_encode(int snum, int job); +void printjob_decode(int jobid, int *snum, int *job); /*The following definitions come from quotas.c */ @@ -620,6 +625,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); /*The following definitions come from replace.c */ @@ -726,22 +732,22 @@ void close_cnum(int cnum, uint16 vuid); BOOL yield_connection(int cnum,char *name,int max_connections); BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear); void exit_server(char *reason); -void standard_sub(int cnum,char *string); +void standard_sub(int cnum,char *str); char *smb_fn_name(int type); int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); int construct_reply(char *inbuf,char *outbuf,int size,int bufsize); /*The following definitions come from shmem.c */ -smb_shm_offset_t smb_shm_alloc(int size); -smb_shm_offset_t smb_shm_addr2offset(void *addr); -smb_shm_offset_t smb_shm_get_userdef_off(void); BOOL smb_shm_create_hash_table( unsigned int size ); BOOL smb_shm_open( char *file_name, int size); BOOL smb_shm_close( void ); +smb_shm_offset_t smb_shm_alloc(int size); BOOL smb_shm_free(smb_shm_offset_t offset); +smb_shm_offset_t smb_shm_get_userdef_off(void); BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off); void * smb_shm_offset2addr(smb_shm_offset_t offset); +smb_shm_offset_t smb_shm_addr2offset(void *addr); BOOL smb_shm_lock_hash_entry( unsigned int entry); BOOL smb_shm_unlock_hash_entry( unsigned int entry ); BOOL smb_shm_get_usage(int *bytes_free, @@ -873,7 +879,7 @@ uint32 file_size(char *file_name); char *attrib_string(int mode); int StrCaseCmp(const char *s, const char *t); int StrnCaseCmp(const char *s, const char *t, int n); -BOOL strequal(const char *s1,const char *s2); +BOOL strequal(const char *s1, const char *s2); BOOL strnequal(const char *s1,const char *s2,int n); BOOL strcsequal(char *s1,char *s2); void strlower(char *s); @@ -951,7 +957,7 @@ BOOL zero_ip(struct in_addr ip); void reset_globals_after_fork(); char *client_name(void); char *client_addr(void); -void standard_sub_basic(char *string); +void standard_sub_basic(char *str); BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); int PutUniCode(char *dst,char *src); struct hostent *Get_Hostbyname(char *name); @@ -968,6 +974,8 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type); int file_lock(char *name,int timeout); void file_unlock(int fd); BOOL is_myname(const char *s); +void set_remote_arch(enum remote_arch_types type); +enum remote_arch_types get_remote_arch(); /*The following definitions come from vt_mode.c */ diff --git a/source/include/smb.h b/source/include/smb.h index f0390230e53..b55c180f361 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -880,6 +880,8 @@ enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER}; enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX, PRINT_QNX,PRINT_PLP,PRINT_LPRNG}; +/* Remote architectures we know about. */ +enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_SAMBA}; /* case handling */ enum case_handling {CASE_LOWER,CASE_UPPER}; diff --git a/source/include/version.h b/source/include/version.h index 56ee92c13f3..afd20f5799d 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.17" +#define VERSION "1.9.17p1" diff --git a/source/lib/charset.c b/source/lib/charset.c index 0bbf99e29f5..c4f67e75fb1 100644 --- a/source/lib/charset.c +++ b/source/lib/charset.c @@ -280,7 +280,7 @@ void codepage_initialise(int client_codepage) if(cp) { - for(i = 0; (cp[i][0] != '\0') && (cp[i][1] != '\0'); i++) + for(i = 0; !((cp[i][0] == '\0') && (cp[i][1] == '\0')); i++) add_dos_char(cp[i][0], (BOOL)cp[i][2], cp[i][1], (BOOL)cp[i][3]); } diff --git a/source/lib/util.c b/source/lib/util.c index d78ecf2728a..7f922def7e3 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -68,6 +68,7 @@ BOOL case_mangle; fstring remote_machine=""; fstring local_machine=""; fstring remote_arch="UNKNOWN"; +static enum remote_arch_types ra_type = RA_UNKNOWN; fstring remote_proto="UNKNOWN"; pstring myhostname=""; pstring user_socket_options=""; @@ -91,7 +92,11 @@ void setup_logging(char *pname,BOOL interactive) if (!interactive) { char *p = strrchr(pname,'/'); if (p) pname = p+1; +#ifdef LOG_DAEMON openlog(pname, LOG_PID, LOG_DAEMON); +#else /* LOG_DAEMON - for old systems that have no facility codes. */ + openlog(pname, LOG_PID); +#endif /* LOG_DAEMON */ } #endif if (interactive) { @@ -3301,13 +3306,13 @@ sub strings with useful parameters Rewritten by Stefaan A Eeckels and Paul Rippin ********************************************************************/ -void standard_sub_basic(char *string) +void standard_sub_basic(char *str) { char *s, *p; char pidstr[10]; struct passwd *pass; - for (s = string ; (p = strchr(s,'%')) != NULL ; s = p ) + for (s = str ; (p = strchr(s,'%')) != NULL ; s = p ) { switch (*(p+1)) { @@ -3864,3 +3869,41 @@ BOOL is_myname(const char *s) DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret)); return(ret); } + +/******************************************************************* +set the horrid remote_arch string based on an enum. +********************************************************************/ +void set_remote_arch(enum remote_arch_types type) +{ + ra_type = type; + switch( type ) + { + case RA_WFWG: + strcpy(remote_arch, "WfWg"); + return; + case RA_OS2: + strcpy(remote_arch, "OS2"); + return; + case RA_WIN95: + strcpy(remote_arch, "Win95"); + return; + case RA_WINNT: + strcpy(remote_arch, "WinNT"); + return; + case RA_SAMBA: + strcpy(remote_arch,"Samba"); + return; + default: + ra_type = RA_UNKNOWN; + strcpy(remote_arch, "UNKNOWN"); + break; + } +} + +/******************************************************************* + Get the remote_arch type. +********************************************************************/ +enum remote_arch_types get_remote_arch() +{ + return ra_type; +} diff --git a/source/nameannounce.c b/source/nameannounce.c index 2f169e9287c..684ef412581 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -430,7 +430,7 @@ workgroup %s\n", am_master, work->work_group)); NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, name, type, 0,0,0, work->work_group,NULL, - False, True, ipzero, ipzero); + ipzero, ipzero); } else if(lp_wins_support()) { diff --git a/source/namepacket.c b/source/namepacket.c index 086e32d9081..d60ef9f6ae2 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -183,10 +183,12 @@ void initiate_netbios_packet(uint16 *id, /**************************************************************************** - reply to a netbios name packet + reply to a netbios name packet. see rfc1002.txt ****************************************************************************/ void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, + int rcode, int rcv_code, int opcode, + BOOL recursion_available, + BOOL recursion_desired, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, char *data,int len) { @@ -197,6 +199,11 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, p = *p1; + if (recursion_available && lp_wins_server()) + { + DEBUG(0,("reply_netbios_packet: r_a not to be used when not a WINS server\n")); + } + switch (rcv_code) { case NMB_STATUS: @@ -240,8 +247,8 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, nmb->header.opcode = opcode; nmb->header.response = True; nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.recursion_available = (lp_wins_support() ? True : False ); - nmb->header.nm_flags.recursion_desired = (lp_wins_support() ? recurse : False ); + nmb->header.nm_flags.recursion_available = recursion_available; + nmb->header.nm_flags.recursion_desired = recursion_desired; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = True; diff --git a/source/nameresp.c b/source/nameresp.c index 23e70a7064d..f44171f4b67 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -117,7 +117,7 @@ static void dead_netbios_entry(struct subnet_record *d, add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, n->nb_flags, GET_TTL(0), - n->reply_to_ip, False, n->reply_to_ip); + n->reply_to_ip, True, n->reply_to_ip); if (!n->bcast && n->num_msgs == 0) { @@ -250,7 +250,6 @@ struct response_record *queue_netbios_pkt_wins( int fd,int quest_type,enum state_type state, char *name,int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip) { /* XXXX note: please see rfc1001.txt section 10 for details on this @@ -260,30 +259,29 @@ struct response_record *queue_netbios_pkt_wins( */ if ((!lp_wins_support()) && (*lp_wins_server())) - { + { /* samba is not a WINS server, and we are using a WINS server */ struct in_addr real_wins_ip; real_wins_ip = *interpret_addr2(lp_wins_server()); - if (!zero_ip(real_wins_ip)) + if (!zero_ip(real_wins_ip)) { - bcast = False; send_ip = real_wins_ip; } - else + else { /* oops. smb.conf's wins server parameter MUST be a host_name or an ip_address. */ DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); } - } + } if (zero_ip(send_ip)) return NULL; return queue_netbios_packet(wins_subnet,fd, quest_type, state, name, name_type, nb_flags, ttl, server_type,my_name,my_comment, - bcast, recurse, send_ip, reply_to_ip); + False, True, send_ip, reply_to_ip); } diff --git a/source/nameserv.c b/source/nameserv.c index 96bb1c0eac8..ccd0ef379cb 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -103,7 +103,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type) /* not a WINS server: we have to release them on the network */ queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, name, type, 0, 0,0,NULL,NULL, - False, True, ipzero, ipzero); + ipzero, ipzero); } } else @@ -163,7 +163,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) queue_netbios_pkt_wins(ClientNMB, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, name, type, nb_flags, GET_TTL(0),0,NULL,NULL, - False, True, ipzero, ipzero); + ipzero, ipzero); } } else @@ -308,7 +308,7 @@ for domain master on workgroup %s\n", myworkgroup)); NAME_QUERY_DOMAIN, myworkgroup, 0x1b, 0, 0,0,NULL,NULL, - False, True, ipzero, ipzero); + ipzero, ipzero); } } } diff --git a/source/nameservreply.c b/source/nameservreply.c index e5976bb7429..5b9c476549d 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -42,7 +42,8 @@ extern struct in_addr wins_ip; send a registration / release response: pos/neg **************************************************************************/ static void send_name_response(int fd, struct in_addr from_ip, - int name_trn_id, int opcode, BOOL success, BOOL recurse, + int name_trn_id, int opcode, BOOL success, + BOOL recursion_available, BOOL recursion_desired, struct nmb_name *reply_name, int nb_flags, int ttl, struct in_addr ip) { @@ -56,7 +57,7 @@ static void send_name_response(int fd, struct in_addr from_ip, /* NEGATIVE RESPONSE */ rcode = 6; } - else if (opcode == NMB_REG && recurse == False) + else if (opcode == NMB_REG && !recursion_available) { /* END-NODE CHALLENGE REGISTRATION RESPONSE */ rcode = 0; @@ -73,7 +74,8 @@ static void send_name_response(int fd, struct in_addr from_ip, p.packet_type = NMB_PACKET; reply_netbios_packet(&p,name_trn_id, - rcode,opcode,opcode,recurse, + rcode,opcode,opcode, + recursion_available, recursion_desired, reply_name, 0x20, 0x1, ttl, rdata, 6); @@ -93,8 +95,10 @@ void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, nb_flags,ttl,REGISTER,register_ip,False,True); /* reply yes or no to the host that requested the name */ + /* see rfc1002.txt - 4.2.10 and 4.2.11 */ send_name_response(fd,from_ip, response_id, NMB_REG, - new_owner, False, + new_owner, + True, True, name, nb_flags, ttl, reply_to_ip); } @@ -160,7 +164,7 @@ subnet %s\n", namestr(&nmb->question.question_name), n->name.name_type, /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL, - success, nmb->header.nm_flags.recursion_desired, + success, False, False, &nmb->question.question_name, nb_flags, 0, ip); } @@ -301,26 +305,29 @@ void reply_name_reg(struct packet_struct *p) /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */ reply_netbios_packet(p,nmb->header.name_trn_id, - 0,NMB_WAIT_ACK,NMB_WAIT_ACK,False, + 0,NMB_WAIT_ACK,NMB_WAIT_ACK, + False,False, reply_name, 0x0a, 0x01, 15*1000, /* 15 seconds long enough to wait? */ rdata, 2); /* initiate some enquiries to the current owner. */ queue_netbios_packet(d,ClientNMB,NMB_QUERY, - NAME_REGISTER_CHALLENGE, - reply_name->name,reply_name->name_type, - nb_flags,0,0,NULL,NULL, - False, False, n->ip_flgs[0].ip, p->ip); + NAME_REGISTER_CHALLENGE, + reply_name->name,reply_name->name_type, + nb_flags,0,0,NULL,NULL, + False, False, + n->ip_flgs[0].ip, p->ip); } else { - /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.13-14 + /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.5-6 or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7 */ send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG, - success, nmb->header.nm_flags.recursion_desired, + success, + True, True, reply_name, nb_flags, ttl, ip); } } @@ -471,7 +478,7 @@ void reply_name_status(struct packet_struct *p) /* Send a POSITIVE NAME STATUS RESPONSE */ reply_netbios_packet(p,nmb->header.name_trn_id, - 0,NMB_STATUS,0,True, + 0,NMB_STATUS,0,False, False, &nmb->question.question_name, 0x21, 0x01, 0, rdata,PTR_DIFF(buf,rdata)); @@ -507,7 +514,10 @@ void reply_name_query(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; + BOOL query_is_to_wins_server = (!bcast && + nmb->header.nm_flags.recursion_desired); int ttl=0; int rcode = 0; int nb_flags = 0; @@ -516,26 +526,31 @@ void reply_name_query(struct packet_struct *p) struct subnet_record *d = NULL; BOOL success = True; struct name_record *n = NULL; + BOOL acting_as_wins_server = lp_wins_support(); /* directed queries are for WINS server: broadcasts are local SELF queries. the exception is Domain Master names. */ - int search = bcast ? FIND_LOCAL | FIND_WINS: FIND_WINS; - - if (search & FIND_LOCAL) + if (query_is_to_wins_server) { - if (!(d = find_req_subnet(p->ip, bcast))) + /* queries to the WINS server involve the WINS server subnet */ + if (!(d = wins_subnet)) { - DEBUG(3,("name query: bcast %s not known\n", + DEBUG(3,("name query: wins search %s not known\n", inet_ntoa(p->ip))); success = False; } } else { - if (!(d = wins_subnet)) + /* queries to the WINS client involve, unfortunately, the WINS subnet + because it contains WINS client (SELF) entries, as _well_ as WINS + server entries. not good. + */ + + if (!(d = find_subnet(*iface_bcast(p->ip)))) { - DEBUG(3,("name query: wins search %s not known\n", + DEBUG(3,("name query: interface for %s not known\n", inet_ntoa(p->ip))); success = False; } @@ -544,12 +559,6 @@ void reply_name_query(struct packet_struct *p) DEBUG(3,("Name query from %s for name %s<0x%x>\n", inet_ntoa(p->ip), question->name, question->name_type)); - if (search == 0) - { - /* eh? no criterion for searching database. help! */ - success = False; - } - if (!bcast && (name_type == 0x1d) && lp_wins_support()) { /* see WINS manager HELP - 'How WINS Handles Special Names' */ @@ -560,7 +569,7 @@ void reply_name_query(struct packet_struct *p) if (success) { /* look up the name in the cache */ - n = find_name_search(&d, question, search, p->ip); + n = find_name_search(&d, question, FIND_LOCAL, p->ip); /* it is a name that already failed DNS lookup or it's expired */ if (n && (n->source == DNSFAIL || @@ -644,10 +653,15 @@ void reply_name_query(struct packet_struct *p) putip(&rdata[2],(char *)&retip); } + /* see rfc1002.txt 4.2.13 */ + reply_netbios_packet(p,nmb->header.name_trn_id, - rcode,NMB_QUERY,0,True, - &nmb->question.question_name, - 0x20, 0x01, - ttl, - rdata, success ? 6 : 0); + rcode,NMB_QUERY,0, + (query_is_to_wins_server && acting_as_wins_server ? + True : False), /* recursion_available flag */ + True, /* recursion_desired_flag */ + &nmb->question.question_name, + 0x20, 0x01, + ttl, + rdata, success ? 6 : 0); } diff --git a/source/nmbsync.c b/source/nmbsync.c index fd85c82e2cd..f2161f631af 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -20,6 +20,8 @@ */ +/* We *must have REPLACE_GETPASS defined here before the includes. */ +#define REPLACE_GETPASS #include "includes.h" extern int ClientNMB; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 8c048ad0798..ad9bf83886d 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -1395,11 +1395,26 @@ check if a config file has changed date BOOL lp_file_list_changed(void) { struct file_lists *f = file_lists; - while (f) { + DEBUG(6,("lp_file_list_changed()\n")); + + while (f) + { pstring n2; + time_t mod_time; + strcpy(n2,f->name); standard_sub_basic(n2); - if (f->modtime != file_modtime(n2)) return(True); + + DEBUG(6,("file %s -> %s last mod_time: %s\n", + f->name, n2, ctime(&f->modtime))); + + mod_time = file_modtime(n2); + + if (f->modtime != mod_time) + { + DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); + return(True); + } f = f->next; } return(False); diff --git a/source/printing/printing.c b/source/printing/printing.c index c4dd9803ebe..c83d2169891 100644 --- a/source/printing/printing.c +++ b/source/printing/printing.c @@ -929,8 +929,8 @@ int get_printqueue(int snum,int cnum,print_queue_struct **queue, if (!printername || !*printername) { - DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n", - lp_servicename(snum),snum)); + DEBUG(6,("xx replacing printer name with service (snum=(%s,%d))\n", + lp_servicename(snum),snum)); printername = lp_servicename(snum); } @@ -1080,3 +1080,23 @@ void status_printjob(int cnum,int snum,int jobid,int status) } + +/**************************************************************************** +we encode print job numbers over the wire so that when we get them back we can +tell not only what print job they are but also what service it belongs to, +this is to overcome the problem that windows clients tend to send the wrong +service number when doing print queue manipulation! +****************************************************************************/ +int printjob_encode(int snum, int job) +{ + return ((snum&0xFF)<<8) | (job & 0xFF); +} + +/**************************************************************************** +and now decode them again ... +****************************************************************************/ +void printjob_decode(int jobid, int *snum, int *job) +{ + (*snum) = (jobid >> 8) & 0xFF; + (*job) = jobid & 0xFF; +} diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk index 08b13d46108..f2b76f20c97 100644 --- a/source/script/mkproto.awk +++ b/source/script/mkproto.awk @@ -64,7 +64,7 @@ BEGIN { next; } -!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^shm_offset_t/ { +!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types/ { next; } diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index e21021c0ac5..55e293d7ffd 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -480,7 +480,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, /* the client expects localtime */ t -= TimeDiff(t); - PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ + PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */ if (uLevel == 1) { PACKS(desc,"B21",queue->user); /* szUserName */ PACKS(desc,"B",""); /* pad */ @@ -1405,11 +1405,10 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded - by the print queue api */ - int snum = (SVAL(p,0)>>8); + int jobid, snum; int i, count; + printjob_decode(SVAL(p,0), &snum, &jobid); /* check it's a supported varient */ if (!(strcsequal(str1,"W") && strcsequal(str2,""))) @@ -1429,7 +1428,7 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, count = get_printqueue(snum,cnum,&queue,NULL); for (i=0;i>8); + int jobid, snum; int uLevel = SVAL(p,2); int function = SVAL(p,4); /* what is this ?? */ int i; char *s = data; + + printjob_decode(SVAL(p,0), &snum, &jobid); *rparam_len = 4; *rparam = REALLOC(*rparam,*rparam_len); @@ -1565,7 +1564,7 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, lpq_reset(snum); count = get_printqueue(snum,cnum,&queue,NULL); for (i=0;i> 8; /*## valid serice number??*/ - job = uJobId & 0xFF; + printjob_decode(SVAL(p,0), &snum, &job); if (snum < 0 || !VALID_SNUM(snum)) return(False); count = get_printqueue(snum,cnum,&queue,&status); for (i = 0; i < count; i++) { - if ((queue[i].job % 0xFF) == job) break; + if ((queue[i].job & 0xFF) == job) break; } if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); desc.base = *rdata; diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index 96e787b07fb..a08402a85ea 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -414,9 +414,9 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) while (*start) { while ((*start) && (*start != '(')) start++; - start++; /* Skip the ( */ if (!*start) continue; /* Always check for the end. */ + start++; /* Skip the ( */ end = start; /* Search for the ' ' or a ')' */ DEBUG(5,("Start of first in pair '%s'\n", start)); while ((*end) && !((*end == ' ') || (*end == ')'))) diff --git a/source/smbd/password.c b/source/smbd/password.c index 2740304cc4f..ed79d658a66 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1576,11 +1576,25 @@ BOOL server_cryptkey(char *buf) p = outbuf+len; name_mangle(desthost,p,' '); len += name_len(p); + p = outbuf+len; /* and my name */ - p = outbuf+len; - name_mangle(remote_machine,p,' '); - len += name_len(p); + /* Fix from Frank Varnavas . + We cannot use the same name as the client to + the NT password server, as NT will drop client + connections if the same client name connects + twice. Instead, synthesize a name from our pid. + and the remote machine name. + */ + { + char buf[32]; /* create name as PIDname */ + sprintf(buf,"%d", getpid()); + strncpy(&buf[strlen(buf)], remote_machine, 31 - strlen(buf)); + buf[31] = '\0'; + DEBUG(1,("negprot w/password server as %s\n",buf)); + name_mangle(buf,p,' '); + len += name_len(p); + } _smb_setlen(outbuf,len); CVAL(outbuf,0) = 0x81; diff --git a/source/smbd/reply.c b/source/smbd/reply.c index cadd63e0457..773063131af 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -261,7 +261,26 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (connection_num < 0) return(connection_error(inbuf,outbuf,connection_num)); - set_message(outbuf,2,strlen(devicename)+1,True); + if (Protocol < PROTOCOL_NT1) + { + set_message(outbuf,2,strlen(devicename)+1,True); + strcpy(smb_buf(outbuf),devicename); + } + else + { + char *fsname = "NTFS"; + char *p; + + set_message(outbuf,3,3,True); + + p = smb_buf(outbuf); + strcpy(p,devicename); p = skip_string(p,1); /* device name */ + strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ + + set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); + + SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ + } DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); @@ -269,8 +288,6 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) SSVAL(inbuf,smb_tid,connection_num); SSVAL(outbuf,smb_tid,connection_num); - strcpy(smb_buf(outbuf),devicename); - return chain_reply(inbuf,outbuf,length,bufsize); } @@ -350,8 +367,24 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); + uint32 client_caps = IVAL(inbuf,smb_vwv11); + enum remote_arch_types ra_type = get_remote_arch(); + char *p = smb_buf(inbuf); + /* client_caps is used as final determination if client is NT or Win95. + This is needed to return the correct error codes in some + circumstances. + */ + + if(ra_type == RA_WINNT || ra_type == RA_WIN95) + { + if(client_caps & (CAP_NT_SMBS | CAP_STATUS32)) + set_remote_arch( RA_WINNT); + else + set_remote_arch( RA_WIN95); + } + if (passlen1 != 24 && passlen2 != 24) doencrypt = False; @@ -2463,7 +2496,7 @@ int reply_printqueue(char *inbuf,char *outbuf) { put_dos_date2(p,0,queue[i].time); CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3); - SSVAL(p,5,queue[i].job); + SSVAL(p,5,printjob_encode(SNUM(cnum), queue[i].job)); SIVAL(p,7,queue[i].size); CVAL(p,11) = 0; StrnCpy(p+12,queue[i].user,16); diff --git a/source/smbd/server.c b/source/smbd/server.c index aaf62fdcad9..24dc8fb51f4 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -397,7 +397,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, dname)) + || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */ { /* we've found the file, change it's name and return */ if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); @@ -1532,7 +1532,12 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; + /* OS/2 Workplace shell fix - may be main code stream in a later release. */ +#ifdef OS2_WPS_FIX + unix_ERR_code = ERRcannotopen; +#else /* OS2_WPS_FIX */ unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; +#endif /* OS2_WPS_FIX */ return; } @@ -1978,6 +1983,19 @@ struct {0,0,0} }; +/* Mapping for old clients. */ + +struct +{ + int new_smb_error; + int old_smb_error; + int protocol_level; + enum remote_arch_types valid_ra_type; +} old_client_errmap[] = +{ + {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT}, + {0,0,0} +}; /**************************************************************************** create an error packet from errno @@ -1998,17 +2016,40 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int else { while (unix_smb_errmap[i].smbclass != 0) - { - if (unix_smb_errmap[i].unixerror == errno) + { + if (unix_smb_errmap[i].unixerror == errno) { eclass = unix_smb_errmap[i].smbclass; ecode = unix_smb_errmap[i].smbcode; break; } i++; - } + } } + /* Make sure we don't return error codes that old + clients don't understand. */ + + /* JRA - unfortunately, WinNT needs some error codes + for apps to work correctly, Win95 will break if + these error codes are returned. But they both + negotiate the *same* protocol. So we need to use + the revolting 'remote_arch' enum to tie break. + + There must be a better way of doing this... + */ + + for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) + { + if(((Protocol < old_client_errmap[i].protocol_level) || + (old_client_errmap[i].valid_ra_type != get_remote_arch())) && + (old_client_errmap[i].new_smb_error == ecode)) + { + ecode = old_client_errmap[i].old_smb_error; + break; + } + } + return(error_packet(inbuf,outbuf,eclass,ecode,line)); } @@ -3025,7 +3066,6 @@ struct { ****************************************************************************/ static int reply_negprot(char *inbuf,char *outbuf) { - extern fstring remote_arch; int outsize = set_message(outbuf,1,0,True); int Index=0; int choice= -1; @@ -3065,22 +3105,22 @@ static int reply_negprot(char *inbuf,char *outbuf) switch ( arch ) { case ARCH_SAMBA: - strcpy(remote_arch,"Samba"); + set_remote_arch(RA_SAMBA); break; case ARCH_WFWG: - strcpy(remote_arch,"WfWg"); + set_remote_arch(RA_WFWG); break; case ARCH_WIN95: - strcpy(remote_arch,"Win95"); + set_remote_arch(RA_WIN95); break; case ARCH_WINNT: - strcpy(remote_arch,"WinNT"); + set_remote_arch(RA_WINNT); break; case ARCH_OS2: - strcpy(remote_arch,"OS2"); + set_remote_arch(RA_OS2); break; default: - strcpy(remote_arch,"UNKNOWN"); + set_remote_arch(RA_UNKNOWN); break; } @@ -3471,12 +3511,12 @@ void exit_server(char *reason) /**************************************************************************** do some standard substitutions in a string ****************************************************************************/ -void standard_sub(int cnum,char *string) +void standard_sub(int cnum,char *str) { if (VALID_CNUM(cnum)) { char *p, *s, *home; - for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) { + for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) { switch (*(p+1)) { case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL) string_sub(p,"%H",home); @@ -3492,7 +3532,7 @@ void standard_sub(int cnum,char *string) } } } - standard_sub_basic(string); + standard_sub_basic(str); } /* diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 80529240590..19c1158658c 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -341,7 +341,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l strcpy(pathreal,Connections[cnum].dirpath); if(needslash) strcat(pathreal,"/"); - strcat(pathreal,fname); + strcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); @@ -368,13 +368,11 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l } } - + name_map_mangle(fname,False,SNUM(cnum)); p = pdata; nameptr = p; - name_map_mangle(fname,False,SNUM(cnum)); - nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL; switch (info_level) @@ -1301,11 +1299,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); -#ifdef OS2_WPS_FIX /* This may become the main code stream in a later release */ - return(ERROR(ERRDOS,ERRcannotopen)); -#else /* OS2_WPS_FIX */ return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); -#endif /* OS2_WPS_FIX */ } switch (info_level) -- cgit From 63c4dc3c69a0ca49e94af94cc9375ba08d2f8b53 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 1997 20:40:34 +0000 Subject: Bringing 1.9.17 patch tree up to date for documentation. Preparing to release 1.9.17p1. Jeremy (jallison@whistle.com) --- WHATSNEW.txt | 41 +++++++++++++++++++++++++++++---- docs/MIRRORS | 33 --------------------------- docs/announce | 2 +- docs/faq/sambafaq-3.html | 2 +- docs/faq/sambafaq.sgml | 2 +- docs/faq/sambafaq.txt | 2 +- docs/history | 2 +- docs/manpages/smb.conf.5 | 11 ++++++--- docs/samba.faq | 2 +- docs/textdocs/BROWSING.txt | 4 ++-- docs/textdocs/DIAGNOSIS.txt | 11 ++++++++- docs/textdocs/DOMAIN.txt | 42 ++++++++++++++++------------------ docs/textdocs/DOMAIN_CONTROL.txt | 2 +- docs/textdocs/GOTCHAS.txt | 4 ++-- docs/textdocs/Passwords.txt | 2 +- docs/textdocs/Support.txt | 49 ++++++++++++++++++++++++++++++++++++++-- docs/textdocs/UNIX-SMB.txt | 4 ++-- docs/textdocs/UNIX_INSTALL.txt | 2 +- 18 files changed, 136 insertions(+), 81 deletions(-) delete mode 100644 docs/MIRRORS diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 6719d439e4f..500a4726bf2 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,8 +1,41 @@ - WHATS NEW IN 1.9.17 - August 25th 1997 - ====================================== + WHATS NEW IN 1.9.17p1 - September 5 1997 + ======================================== -New stable release of Samba. ----------------------------- +New stable patch release: Samba - version 1.9.17p1. +--------------------------------------------------- + +This is a patch release which superceedes the +last stable release of Samba, release 1.9.17. +This release fixes the few bugs that users reported +in the previous stable release (1.9.17). + +These bugfixes are : + +Fix for DOS and Windows 95 clients having trouble +delting files on a Samba share in a DOS command line +environment. + +Fixes to set the 'flag' bits correctly when talking to a +non-Samba WINS server. + +Fix for NT clients being dropped when using security=server. + +Fixes to the printer queue reporting code. + +Fix for the name map mangle bug (mangling .html -> .htm was +not working). + +If you are not affected by any of these problems then there +is no need to upgrade. + +The release notes from the previous stable release follow. + +The Samba Team. + +-------------Previous release notes------------------------- + +New stable release of Samba - 1.9.17 +------------------------------------ This is the new stable release of Samba, superceeding the last stable release 1.9.16p11. All users are diff --git a/docs/MIRRORS b/docs/MIRRORS deleted file mode 100644 index a055860e999..00000000000 --- a/docs/MIRRORS +++ /dev/null @@ -1,33 +0,0 @@ -The main Samba ftp site is samba.anu.edu.au in pub/samba/. Contact -samba-bugs@samba.anu.edu.au for help with this site. - -Mirror sites include: - -ftp://nimbus.anu.edu.au/pub/tridge/samba -ftp://sunsite.auc.dk/pub/unix/networking/samba/ -ftp://src.doc.ic.ac.uk/packages/samba/ -ftp://choc.satech.net.au/pub/samba/ -ftp://ftp.uni-trier.de/pub/unix/network/samba/ -ftp://sunsite.mff.cuni.cz/Net/Protocols/Samba/ -ftp://ring.aist.go.jp/archives/net/samba/ -ftp://ring.asahi-net.or.jp/archives/net/samba/ -ftp://ftp.cs.ucr.edu/pub/software/samba -ftp://ftp.ua.pt/pub/misc/samba/ -ftp://sunsite.unc.edu/pub/Linux/system/Network/samba/ - -There are several others. Give archie a try. - -SCO binaries available from: -ftp://ftp.markv.com/pub/samba (built by lance@fox.com) - -AIX and DEC OSF/1 binaries are available from: -ftp://151.99.220.5/pub/samba (built by davide.migliavacca@inferentia.inet.it) - -QNX binaries and source code: -ftp://quics.qnx.com/usr/free/staging/samba - -Http sites include: - -http://samba.canberra.edu.au/pub/samba -http://www.choc.satech.net.au/pub/samba/ - diff --git a/docs/announce b/docs/announce index 18e34b68c2b..adcde8966f8 100644 --- a/docs/announce +++ b/docs/announce @@ -28,7 +28,7 @@ allows you to access a SMB printer (such as one attached to an OS/2 or WfWg server) from Unix, using an entry in /etc/printcap, or by explicitly specifying the command used to print files. -What are it's features? +What are its features? ------------------------ Samba supports many features that are not supported in other SMB diff --git a/docs/faq/sambafaq-3.html b/docs/faq/sambafaq-3.html index 39cded21ec1..8b24de54f23 100644 --- a/docs/faq/sambafaq-3.html +++ b/docs/faq/sambafaq-3.html @@ -85,7 +85,7 @@ To syncronize your PC's clock with your Samba server: Each time you start your computer (or login for Win95) your PC will -synchronize it's clock with your Samba server.

+synchronize its clock with your Samba server.

Alternativley, if you clients support Domain Logons, you can setup Domain Logons with Samba - see: BROWSING.txt *** for more information.

diff --git a/docs/faq/sambafaq.sgml b/docs/faq/sambafaq.sgml index 7a618d47c8f..951ad822edb 100644 --- a/docs/faq/sambafaq.sgml +++ b/docs/faq/sambafaq.sgml @@ -570,7 +570,7 @@ To syncronize your PC's clock with your Samba server: Close the properties dialog box by choosing 'OK' Each time you start your computer (or login for Win95) your PC will -synchronize it's clock with your Samba server. +synchronize its clock with your Samba server. Alternativley, if you clients support Domain Logons, you can setup Domain Logons with Samba - see: *** for more information. diff --git a/docs/faq/sambafaq.txt b/docs/faq/sambafaq.txt index 2bc45fb7945..e7f5f32a20d 100644 --- a/docs/faq/sambafaq.txt +++ b/docs/faq/sambafaq.txt @@ -841,7 +841,7 @@ o Close the properties dialog box by choosing 'OK' Each time you start your computer (or login for Win95) your PC will - synchronize it's clock with your Samba server. + synchronize its clock with your Samba server. Alternativley, if you clients support Domain Logons, you can setup Domain Logons with Samba - see: BROWSING.txt diff --git a/docs/history b/docs/history index a86160e854d..dd9e83719ff 100644 --- a/docs/history +++ b/docs/history @@ -112,7 +112,7 @@ code! I wrote back saying it was OK, but never heard from him again. I don't know if it went on the cd-rom. Anyway, the next big event was in December 1993, when Dan again sent -me an e-mail saying my server had "raised it's ugly head" on +me an e-mail saying my server had "raised its ugly head" on comp.protocols.tcpip.ibmpc. I had a quick look on the group, and was surprised to see that there were people interested in this thing. diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 1eed1fcd868..a0a96f26ff6 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -1585,7 +1585,7 @@ see "debug level" .SS logon path (G) This parameter specifies the home directory where roaming profiles -(USER.DAT / USER.MAN files) are stored. +(USER.DAT / USER.MAN files for Windows 95) are stored. This option takes the standard substitutions, allowing you to have separate logon scripts for each user or machine. It also specifies @@ -1603,11 +1603,16 @@ be made read-only. It is not adviseable that the USER.DAT file be made read-only - rename it to USER.MAN to achieve the desired effect (a MANdatory profile). +Windows clients can sometimes maintain a connection to the [homes] +share, even though there is no user logged in. Therefore, it is +vital that the logon path does not include a reference to the +homes share (i.e \\\\%L\\HOMES\profile_path will cause problems). + .B Default: - logon path = \\\\%L\\%U + logon path = \\\\%L\\%U\\profile .B Example: - logon path = \\\\PROFILESERVER\\HOME_DIR\\%U + logon path = \\\\PROFILESERVER\\HOME_DIR\\%U\\PROFILE .SS logon script (G) diff --git a/docs/samba.faq b/docs/samba.faq index e74585b9769..19126439500 100644 --- a/docs/samba.faq +++ b/docs/samba.faq @@ -605,7 +605,7 @@ To syncronize your PC's clock with your Samba server: * Close the properties dialog box by choosing 'OK' Each time you start your computer (or login for Win95) your PC will -synchronize it's clock with your Samba server. +synchronize its clock with your Samba server. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt index 12d3417a294..d8362f15299 100644 --- a/docs/textdocs/BROWSING.txt +++ b/docs/textdocs/BROWSING.txt @@ -320,7 +320,7 @@ all smb.conf files : wins server = where is either the DNS name of the WINS server -machine or it's IP address. +machine or its IP address. Note that this line MUST NOT BE SET in the smb.conf file of the Samba server acting as the WINS server itself. If you set both the @@ -358,7 +358,7 @@ server as a domain master browser set the following option in the domain master = yes The domain master browser should also preferrably be the local master -browser for it's own subnet. In order to achieve this set the following +browser for its own subnet. In order to achieve this set the following options in the [global] section of the smb.conf file : domain master = yes diff --git a/docs/textdocs/DIAGNOSIS.txt b/docs/textdocs/DIAGNOSIS.txt index 5f20f610310..11eb91b2ff8 100644 --- a/docs/textdocs/DIAGNOSIS.txt +++ b/docs/textdocs/DIAGNOSIS.txt @@ -69,7 +69,12 @@ run ping. If you get a message saying "host not found" or similar then your DNS software or /etc/hosts file is not correctly setup. It is possible to run samba without DNS entries for the server and client, but I assume -you do have correct entries for the remainder of these tests. +you do have correct entries for the remainder of these tests. + +Another reason why ping might fail is if your host is running firewall +software. You will need to relax the rules to let in the workstation +in question, perhaps by allowing access from another subnet (on Linux +this is done via the ipfwadm program.) TEST 3: @@ -208,6 +213,10 @@ same fixes apply as they did for the "smbclient -L" test above. In particular, make sure your "hosts allow" line is correct (see the man pages) +If you get "specified computer is not receiving requests" or similar +it probably means that the host is not contactable via tcp services. +Check to see if the host is running tcp wrappers, and if so add an entry in +the hosts.allow file for your client (or subnet, etc.) TEST 9: diff --git a/docs/textdocs/DOMAIN.txt b/docs/textdocs/DOMAIN.txt index 547e1b6cf8c..3cd8a125b7b 100644 --- a/docs/textdocs/DOMAIN.txt +++ b/docs/textdocs/DOMAIN.txt @@ -1,30 +1,21 @@ Contributor: Samba Team -Updated: August 25, 1997 +Updated: June 27, 1997 Subject: Network Logons and Roving Profiles =========================================================================== A domain and a workgroup are exactly the same thing in terms of network -traffic, except for the client logon sequence. Some kind of distributed -authentication database is associated with a domain (there are quite a few -choices) and this adds so much flexibility that many people think of a -domain as a completely different entity to a workgroup. From Samba's -point of view a client connecting to a service presents an authentication -token, and it if it is valid they have access. Samba does not care what -mechanism was used to generate that token in the first place. +browsing. The difference is that a distributable authentication +database is associated with a domain, for secure login access to a +network. Also, different access rights can be granted to users if they +successfully authenticate against a domain logon server (samba does not +support this, but NT server and other systems based on NT server do). The SMB client logging on to a domain has an expectation that every other server in the domain should accept the same authentication information. However the network browsing functionality of domains and workgroups is identical and is explained in BROWSING.txt. -There are some implementation differences: Windows 95 can be a member of -both a workgroup and a domain, but Windows NT cannot. Windows 95 also -has the concept of an "alternative workgroup". Samba can only be a -member of a single workgroup or domain, although this is due to change -with a future version when nmbd will be split into two daemons, one -for WINS and the other for browsing (NetBIOS.txt explains what WINS is.) - Issues related to the single-logon network model are discussed in this document. Samba supports domain logons, network logon scripts, and user profiles. The support is still experimental, but it seems to work. @@ -32,10 +23,8 @@ profiles. The support is still experimental, but it seems to work. The support is also not complete. Samba does not yet support the sharing of the Windows NT-style SAM database with other systems. However this is only one way of having a shared user database: exactly the same effect can -be achieved by having all servers in a domain share a distributed NIS, -Kerberos or other authentication database. These other options may or may -not involve changes to the client software, that depends on the combination -of client OS, server OS and authentication protocol. +be achieved by having all servers in a domain share a distributed NIS or +Kerberos authentication database. When an SMB client in a domain wishes to logon it broadcast requests for a logon server. The first one to reply gets the job, and validates its @@ -147,8 +136,9 @@ In the [global] section of smb.conf set the following (for example): logon path = \\profileserver\profileshare\profilepath\%U\moreprofilepath -The default for this option is \\%L\%U, namely \\sambaserver\username, -The \\L%\%U services is created automatically by the [homes] service. +The default for this option is \\%L\%U\profile, namely +\\sambaserver\username\profile. The \\L%\%U services is created +automatically by the [homes] service. If you are using a samba server for the profiles, you _must_ make the share specified in the logon path browseable. Windows 95 appears to @@ -158,6 +148,10 @@ away. It also attempts to create the components of the full path for you. If the creation of any component fails, or if it cannot see any component of the path, the profile creation / reading fails. +[lkcl 26aug96 - we have discovered a problem where Windows clients can +maintain a connection to the [homes] share in between logins. The +[homes] share must NOT therefore be used in a profile path.] + Windows 95 ---------- @@ -281,8 +275,10 @@ to specify the location of the profile. Samba cannot be a domain logon server for NT, therefore you will need to manually configure each and every account. [lkcl 10aug97 - i tried setting the path in each account to \\samba-server\homes\profile, and discovered that -this fails for some reason. you have to have \\samba-server\user\profile, -where user is the username created from the [homes] share]. +this fails because a background process maintains the connection to +the [homes] share which does _not_ close down in between user logins. +you have to have \\samba-server\user\profile, where user is the +username created from the [homes] share]. The entry for the NT 4.0 profile is a _directory_ not a file. The NT help on profiles mentions that a directory is also created with a .PDS diff --git a/docs/textdocs/DOMAIN_CONTROL.txt b/docs/textdocs/DOMAIN_CONTROL.txt index bebac3e900c..0b077320cdb 100644 --- a/docs/textdocs/DOMAIN_CONTROL.txt +++ b/docs/textdocs/DOMAIN_CONTROL.txt @@ -94,7 +94,7 @@ have at least one Backup Domain Controller (BDC). The PDC and BDCs then participate in replication of the SAM database so that each Domain Controlling participant will have an up to date SAM component -within it's registry. +within its registry. Samba can NOT at this time function as a Domain Controller for any of these security services, but like all other domain members can interact with the diff --git a/docs/textdocs/GOTCHAS.txt b/docs/textdocs/GOTCHAS.txt index d4e5f3e842d..bc5c6dae853 100644 --- a/docs/textdocs/GOTCHAS.txt +++ b/docs/textdocs/GOTCHAS.txt @@ -48,10 +48,10 @@ Details: Windows NT checks at start up to see if any domain logon controllers are already running within the domain. It finds Samba claiming to offer the service and therefore does NOT - start it's Network Logon Service. + start its Network Logon Service. Windows NT needs the Windows NT network logon service to gain - from it's Domain controller's SAM database the security + from its Domain controller's SAM database the security identifier for the user loging on. Work-around: Stop the Samba nmbd and smbd processes, then on the Windows diff --git a/docs/textdocs/Passwords.txt b/docs/textdocs/Passwords.txt index 3d7acac9dd3..f76010c4608 100644 --- a/docs/textdocs/Passwords.txt +++ b/docs/textdocs/Passwords.txt @@ -37,7 +37,7 @@ only written and tested for AFS 3.3 and later. SECURITY = SERVER ================= -Samba can use a remote server to do it's username/password +Samba can use a remote server to do its username/password validation. This allows you to have one central machine (for example a NT box) control the passwords for the Unix box. diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index a4fd34aca62..afffc2be505 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -17,6 +17,8 @@ If you want to be added to the list, or want your entry modified then contact the address below. Please make sure to include a header line giving the region and country, eg CANBERRA - AUSTRALIA. +The Samba Team reserves the right not to add support providers. + You can contact the maintainers at samba-bugs@samba.anu.edu.au The support list has now been re-arranged into geographical areas @@ -27,7 +29,7 @@ Region Number of entries ---------------------------------------------------- AFRICA 2 AMERICA - CENTRAL & SOUTH 3 - AMERICA - USA 31 + AMERICA - USA 33 ASIA 1 AUSTRALIA & NEW ZEALAND 18 CANADA 8 @@ -299,7 +301,7 @@ Email: jay@wss.net ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -FORT COLLINS, CO - USA +FORT COLLINS, COLORADO - USA Granite Computing Solutions ATTN: Brian Grossman @@ -314,6 +316,23 @@ WWW solutions. WWW education. Unix education. Custom software development - eg. http://www.SoftHome.Net/modsim/. ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +COLORADO - USA + +Daylight Software +1062 Lexington Lane +Estes Park, CO 80517 USA +(970) 586-6058 + +We have experience with Samba under SunOS, Solaris and Linux, +and also with Windows NT and Microsoft Lan Manager. + +Contact: daylight@frii.net + +Chris Howard Daylight Software +daylight@frii.net Estes Park, Colorado USA +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ FLORIDA - USA @@ -384,6 +403,32 @@ Florida area. We are well familiar in the integration of SAMBA and NT and in SAMBA configuration on AIX, SCO, Linux And SUN Solaris. ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +FLORIDA - USA + +The PC Doctor +Tampa Bay Interactive +1314 Tampa Rd STE 120 +Palm Harbor, FL 34683 + +ph 813.781-2209 +fx 813.571-3805 + +Contacts: Jared Hall: jhall@tbi.net + System Operations: support@tbi.net + +Tampa Bay Interactive provides complete Internet solutions for the Small +Office and Home Office. Specializing in Intel-Based UNIX systems; Linux, +BSD/OS, FreeBSD, SCO. Proxy Server specialists. + +~~ Jared Hall ~~~~~~~ Tampa Bay Interactive +~~~~~~~~~~~~~~~~~~~~~ 1314 Tampa Rd, #120 +~~ jhall@tbi.net ~~~~ Palm Harbor, FL 34683 +~~ (813) 781-2209 ~~~ (http://www.tbi.net) + +Telecom Corner - http://www.tbi.net/~jhall +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ GEORGIA - USA diff --git a/docs/textdocs/UNIX-SMB.txt b/docs/textdocs/UNIX-SMB.txt index 88a7324dd73..ec2e657c052 100644 --- a/docs/textdocs/UNIX-SMB.txt +++ b/docs/textdocs/UNIX-SMB.txt @@ -88,7 +88,7 @@ passwords they are in trouble. Samba can try to cope with this by either using the "password level" option which causes Samba to try the offered password with up to the specified number of case changes, or by using the "password server" -option which allows Samba to do it's validation via another machine +option which allows Samba to do its validation via another machine (typically a WinNT server). Samba supports the password encryption method used by SMB @@ -128,7 +128,7 @@ The second major problem is the "opportunistic locking" requested by some clients. If a client requests opportunistic locking then it is asking the server to notify it if anyone else tries to do something on the same file, at which time the client will say if it is willing to -give up it's lock. Unix has no simple way of implementing +give up its lock. Unix has no simple way of implementing opportunistic locking, and currently Samba has no support for it. Deny Modes diff --git a/docs/textdocs/UNIX_INSTALL.txt b/docs/textdocs/UNIX_INSTALL.txt index 8b430a98844..c189482ca41 100644 --- a/docs/textdocs/UNIX_INSTALL.txt +++ b/docs/textdocs/UNIX_INSTALL.txt @@ -315,7 +315,7 @@ codes of locking calls to tell clients that everything is OK. The second class of locking is the "deny modes". These are set by an application when it opens a file to determine what types of access -should be allowed simultaneously with it's open. A client may ask for +should be allowed simultaneously with its open. A client may ask for DENY_NONE, DENY_READ, DENY_WRITE or DENY_ALL. There are also special compatability modes called DENY_FCB and DENY_DOS. -- cgit From d684d276fbeb9a4f53840df8a47f6ca6ede8bd55 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 1997 21:49:07 +0000 Subject: client.c: status.c: Ensure that myhostname is set so that substitutions work. server.c: Sync up with main branch. Jermey (jallison@whistle.com) --- source/client/client.c | 6 ++++++ source/smbd/server.c | 3 ++- source/utils/status.c | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/source/client/client.c b/source/client/client.c index 329956ce94b..4718db84ac0 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -34,6 +34,7 @@ pstring cd_path = ""; pstring service=""; pstring desthost=""; extern pstring myname; +extern pstring myhostname; pstring password = ""; pstring username=""; pstring workgroup=""; @@ -4625,6 +4626,11 @@ static void usage(char *pname) DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); + if(!get_myname(myhostname,NULL)) + { + DEBUG(0,("Failed to get my hostname.\n")); + } + if (!lp_load(servicesf,True)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 24dc8fb51f4..d4407269f0b 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1532,12 +1532,13 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (strstr(fname,".+,;=[].")) { unix_ERR_class = ERRDOS; - /* OS/2 Workplace shell fix - may be main code stream in a later release. */ + /* OS/2 Workplace shell fix may be main code stream in a later release. */ #ifdef OS2_WPS_FIX unix_ERR_code = ERRcannotopen; #else /* OS2_WPS_FIX */ unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; #endif /* OS2_WPS_FIX */ + return; } diff --git a/source/utils/status.c b/source/utils/status.c index b439741e6c6..6fa85c0a630 100644 --- a/source/utils/status.c +++ b/source/utils/status.c @@ -188,13 +188,13 @@ locking version (was %d, should be %d).\n",fname, } } + get_myname(myhostname, NULL); + if (!lp_load(servicesf,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); return (-1); } - get_myname(myhostname, NULL); - if (verbose) { printf("using configfile = %s\n", servicesf); printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL"); -- cgit From 91f482026df92da804fbd0344c83807c9a2e775e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 11 Sep 1997 00:19:26 +0000 Subject: locking.c: Fix to make slow share mode file 0666 instead of 0644. Stoped smbstatus from reporting correct locks. nameelect.c: Luke's fix for elections. namepacket.c: Removed iritating error message. nmblookup.c: Fixed bug where status request went to random IP address. reply.c: Changed NTFS to SAMBA in filename string. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 2 +- source/nameelect.c | 2 +- source/namepacket.c | 5 ----- source/smbd/reply.c | 2 +- source/utils/nmblookup.c | 16 ++++++++++++---- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index f579a75a0bc..760d21a05d8 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -616,7 +616,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok #ifdef SECURE_SHARE_MODES fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) diff --git a/source/nameelect.c b/source/nameelect.c index 06f3e870af1..4666b22588c 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -76,7 +76,7 @@ void check_master_browser(time_t t) { if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work)) { - if (lp_local_master()) + if (lp_local_master() && lp_preferred_master()) { /* potential master browser - not a master browser. force becoming a master browser, hence the log message. diff --git a/source/namepacket.c b/source/namepacket.c index d60ef9f6ae2..44e449b8c2a 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -199,11 +199,6 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, p = *p1; - if (recursion_available && lp_wins_server()) - { - DEBUG(0,("reply_netbios_packet: r_a not to be used when not a WINS server\n")); - } - switch (rcv_code) { case NMB_STATUS: diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 773063131af..3ef37052dbe 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -268,7 +268,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) } else { - char *fsname = "NTFS"; + char *fsname = "SAMBA"; char *p; set_message(outbuf,3,3,True); diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c index 582f4eb6db3..25c94dcd6a0 100644 --- a/source/utils/nmblookup.c +++ b/source/utils/nmblookup.c @@ -192,17 +192,25 @@ int main(int argc,char *argv[]) retries = 1; } - if (name_query(ServerFD,lookup,lookup_type,bcast,True, + if (name_query(ServerFD,lookup,lookup_type,bcast,True, bcast_addr,&ip,NULL)) - { - printf("%s %s\n",inet_ntoa(ip),lookup); - } + { + printf("%s %s\n",inet_ntoa(ip),lookup); + + /* We can only do find_status if the ip address returned + was valid - ie. name_query returned true. + */ if (find_status) { printf("Looking up status of %s\n",inet_ntoa(ip)); name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL); printf("\n"); } + } + else + { + printf("name_query failed to find name %s\n", lookup); + } } return(0); -- cgit From 87644499eac889a4c83c05f473883488cbdb710d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Sep 1997 16:31:51 +0000 Subject: Fixed bug where user connecting with guest username and no password was not being seen as guest. Bug was introduced in previous patch. Jeremy (jallison@whistle.com) --- source/smbd/reply.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 3ef37052dbe..228d8ad6692 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -459,6 +459,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) add_session_user(user); + /* Check if the given username was the guest user with no password. + We need to do this check after add_session_user() as that + call can potentially change the username (via map_user). + */ + + if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) + guest = True; if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && !check_hosts_equiv(user)) -- cgit From cfd4461be4522f1dd64d43e8a59f8baeed64f177 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 1997 20:02:20 +0000 Subject: Keep consultants in sync. --- docs/textdocs/Support.txt | 59 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index afffc2be505..6257872098a 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -29,11 +29,11 @@ Region Number of entries ---------------------------------------------------- AFRICA 2 AMERICA - CENTRAL & SOUTH 3 - AMERICA - USA 33 + AMERICA - USA 35 ASIA 1 AUSTRALIA & NEW ZEALAND 18 CANADA 8 - EUROPE 33 + EUROPE 34 MIDDLE EAST 1 AFRICA @@ -223,6 +223,28 @@ To find out more about our company, look at our website: http://www.acclaim.com ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +BAY AREA, BERKELEY CALIFORNIA - USA + +Vortex Technology Services + +2467 Warring St Suite 206, Berkeley CA 94704 + +Phone/Fax : (510) 540-VTEX E-Mail: support@vtex.net + (510) 540-8839 + +Contact: Paul Puey, Chief Network Consultant/Engineer + +Vortex Technology is a fast growing technical service company based in +Berkeley, California. Our Co-founders are composed entirely of UC +Berkeley engineering graduates with a broad range of skills in the +technical consultation fields. We provide bay area companies with +professional web site and database design, LAN and WAN consultation, and +custom programming. We ourselves use a mixed NT / Linux Samba server +environment in our office. We are very experienced with Samba +administration as well as administration of UNIX and NT networks. +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ CALIFORNIA - USA @@ -628,6 +650,23 @@ US dollars per hour. Please contact us for more information on our rates and services. ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +TEXAS - USA + +The Solutions Group +P.O. Box 31400 +Houston, TX 77231-1400 + +Voice: (713) 729-2602 +Fax: (713) 723-9387 +Email: chuckb@LinuxTX.com + +The Solutions Group provides support for Linux, Solaris, and SCO UNIX. +We specialize in mixed environments using Samba. We are certified NT +as well as UNIX specialists. We can provide onsite support in the +Houston area and remote support in any other areas. +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ UNITED STATES @@ -1591,6 +1630,22 @@ Digital Unix Macintosh ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +ROME - ITALY + +Company: Pantheon Srl + Via del Tritone 132 + 00187 ROME - ITALY + +Phone/Fax: +39 6 47823666 +URL: http://www.pantheon.it + +Contact: Dario Centofanti + +Pantheon provide support for SaMBa and other TCP/IP applications running +under Linux. We are also an internet provider. +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ VICENZA - ITALY -- cgit From f8998b9dac5c86e5a12f730837aa7f24c24f1bf1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 1997 17:08:00 +0000 Subject: Ensuring malloced memory is bzero'd. Jeremy (jallison@whistle.com) --- source/namedbname.c | 2 ++ source/namedbresp.c | 2 ++ source/namedbwork.c | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/source/namedbname.c b/source/namedbname.c index c91541cc815..a45a749f140 100644 --- a/source/namedbname.c +++ b/source/namedbname.c @@ -486,6 +486,8 @@ struct name_record *add_netbios_entry(struct subnet_record *d, return NULL; } + bzero((char *)n->ip_flgs, sizeof(*n->ip_flgs) * n->num_ips); + make_nmb_name(&n->name,name,type,scope); if ((n2 = find_name_search(&found_subnet, &n->name, search, new_only?ipzero:ip))) diff --git a/source/namedbresp.c b/source/namedbresp.c index 98f8ca774bc..86d7eddbd41 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -104,6 +104,8 @@ struct response_record *make_response_queue_record(enum state_type state, if (!(n = (struct response_record *)malloc(sizeof(*n)))) return(NULL); + bzero((char *)n, sizeof(*n)); + n->response_id = id; n->state = state; n->fd = fd; diff --git a/source/namedbwork.c b/source/namedbwork.c index 2982ffd3e78..a6260aab467 100644 --- a/source/namedbwork.c +++ b/source/namedbwork.c @@ -84,7 +84,8 @@ static struct work_record *make_workgroup(char *name) work = (struct work_record *)malloc(sizeof(*work)); if (!work) return(NULL); - + bzero((char *)work, sizeof(*work)); + StrnCpy(work->work_group,name,sizeof(work->work_group)-1); work->serverlist = NULL; @@ -92,6 +93,7 @@ static struct work_record *make_workgroup(char *name) SV_TYPE_POTENTIAL_BROWSER : 0 ); work->RunningElection = False; work->ElectionCount = 0; + work->announce_interval = 0; work->needelection = False; work->needannounce = True; work->mst_state = MST_POTENTIAL; -- cgit From c044da646c613e1e955072937fd7d0ded8b344ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Sep 1997 00:48:54 +0000 Subject: Added South American consultant. --- docs/textdocs/Support.txt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index 6257872098a..0a5c41b1950 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -28,7 +28,7 @@ These are currently: Region Number of entries ---------------------------------------------------- AFRICA 2 - AMERICA - CENTRAL & SOUTH 3 + AMERICA - CENTRAL & SOUTH 4 AMERICA - USA 35 ASIA 1 AUSTRALIA & NEW ZEALAND 18 @@ -80,6 +80,25 @@ AMERICA - CENTRAL & SOUTH ========================= +------------------------------------------------------------------------------ +ARGENTINA - SOUTH AMERICA + +Buenos Aires - Argentina + +Guillermo Sansovic +Email: gui@usa.net +Arkham Software +Rivadavia 923 Piso 8 +1002 Buenos Aires +Argentina + +Tel: + 54 1 345-0645 + +At Arkham Software we have been working with Unix systems since 1986. We do +intranets, software development and system integration. Our experience ith +Samba dates from 1995. +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ CHILE - SOUTH AMERICA -- cgit From c701db19e14d1b53103acbb8f7abe4c8bc2c3614 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 22 Sep 1997 22:09:07 +0000 Subject: Makefile: Added glibc2 fixes for Linux. includes.h: Added glibc2 fixes for Linux. quotas.c: Added OSF1 fix. reply.c: Added fix from Ray Frush to fix zero times for NT clients. Also added old client session keepalives. Jeremy (jallison@whistle.com) --- source/include/includes.h | 8 ++++++++ source/smbd/quotas.c | 20 ++++++++++++++++---- source/smbd/reply.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/source/include/includes.h b/source/include/includes.h index a63f8f8597c..e66ceb2d70c 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -217,6 +217,14 @@ Here come some platform specific sections #ifndef NO_ASMSIGNALH #include #endif +#ifdef GLIBC2 +#define _LINUX_C_LIB_VERSION_MAJOR 6 +#include +#include +#include +#include +#include +#endif #define SIGNAL_CAST (__sighandler_t) #define USE_GETCWD #define USE_SETSID diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index d19d386e273..d4f746c9e36 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -373,22 +373,34 @@ try to get the disk space from disk quotas - OFS1 version BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) { uid_t user_id, euser_id; - int r; + int r, save_errno; struct dqblk D; struct stat S; euser_id = geteuid(); user_id = getuid(); - setreuid(euser_id, euser_id); + setreuid(euser_id, -1); r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); - if (setreuid(user_id, euser_id) == -1) + if (r) + save_errno = errno; + + if (setreuid(user_id, -1) == -1) DEBUG(5,("Unable to reset uid to %d\n", user_id)); *bsize = DEV_BSIZE; if (r) - return(False); + { + if (save_errno == EDQUOT) // disk quota exceeded + { + *dfree = 0; + *dsize = D.dqb_curblocks; + return (True); + } + else + return (False); + } /* Use softlimit to determine disk space, except when it has been exceeded */ diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 228d8ad6692..a15185146da 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -65,19 +65,18 @@ int reply_special(char *inbuf,char *outbuf) smb_setlen(outbuf,0); - switch (msg_type) - { + switch (msg_type) { case 0x81: /* session request */ CVAL(outbuf,0) = 0x82; CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) - { + if (name_len(inbuf+4) > 50) { DEBUG(0,("Invalid name length in session request\n")); return(0); } name_extract(inbuf,4,name1); name_extract(inbuf,4 + name_len(inbuf + 4),name2); - DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2)); + DEBUG(2,("netbios connect: name1=%s name2=%s\n", + name1,name2)); strcpy(remote_machine,name2); trim_string(remote_machine," "," "); @@ -97,12 +96,26 @@ int reply_special(char *inbuf,char *outbuf) reopen_logs(); break; + + case 0x89: /* session keepalive request + (some old clients produce this?) */ + CVAL(outbuf,0) = 0x85; + CVAL(outbuf,3) = 0; + break; + + case 0x82: /* positive session response */ + case 0x83: /* negative session response */ + case 0x84: /* retarget session response */ + DEBUG(0,("Unexpected session response\n")); + break; + case 0x85: /* session keepalive */ default: return(0); } - DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags)); + DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n", + timestring(),msg_type,msg_flags)); return(outsize); } @@ -3532,11 +3545,31 @@ int reply_setattrE(char *inbuf,char *outbuf) unix_times.actime = make_unix_date2(inbuf+smb_vwv3); unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); + /* + * Patch from Ray Frush + * Sometimes times are sent as zero - ignore them. + */ + + if ((unix_times.actime == 0) && (unix_times.modtime == 0)) + { + /* Ignore request */ + DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \ +not setting timestamps of 0\n", + timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); + return(outsize); + } + else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) + { + /* set modify time = to access time if modify time was 0 */ + unix_times.modtime = unix_times.actime; + } + /* Set the date on this file */ if(sys_utime(Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); + DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", + timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); return(outsize); } -- cgit From e8dd34b0d3ba704deff696c1683297536a494893 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 26 Sep 1997 12:39:45 +0000 Subject: This commit fixes the security hole due to buffer overflows. The main fix is just a couple of lines long, but I have now also put precautionary checks on a large number of other places in the code where unchecked string copies were being performed. An exploit via one of these copies is unlikely, but is is better to be safe. I also added a routine to log possible exploit attempts using the code that was posted for obtaining root access on a Samba server. --- source/client/clientutil.c | 21 ++++---- source/include/local.h | 2 + source/include/proto.h | 2 + source/lib/system.c | 4 +- source/lib/time.c | 4 +- source/lib/username.c | 4 +- source/lib/util.c | 114 +++++++++++++++++++++++++++++---------- source/libsmb/nmblib.c | 4 +- source/locking/locking.c | 2 +- source/nameannounce.c | 4 +- source/namedbname.c | 8 +-- source/namedbsubnet.c | 4 +- source/nameelect.c | 2 +- source/namelogon.c | 6 +-- source/nmbd/nmbd.c | 22 ++++---- source/nmbsync.c | 4 +- source/param/loadparm.c | 8 +-- source/printing/pcap.c | 4 +- source/printing/printing.c | 36 ++++++------- source/smbd/chgpasswd.c | 12 ++--- source/smbd/dir.c | 2 +- source/smbd/ipc.c | 29 ++++++---- source/smbd/mangle.c | 8 +-- source/smbd/message.c | 14 ++--- source/smbd/pipes.c | 4 +- source/smbd/reply.c | 131 +++++++++++++++++++++++++++------------------ source/smbd/server.c | 36 ++++++------- source/smbd/trans2.c | 28 ++++++---- source/smbd/vt_mode.c | 12 ++--- source/utils/nmblookup.c | 6 +-- 30 files changed, 320 insertions(+), 217 deletions(-) diff --git a/source/client/clientutil.c b/source/client/clientutil.c index b4f0849c5fe..1b59946ff5b 100644 --- a/source/client/clientutil.c +++ b/source/client/clientutil.c @@ -171,7 +171,8 @@ BOOL cli_send_session_request(char *inbuf, char *outbuf) int len = 4; /* send a session request (RFC 8002) */ - strcpy(dest,desthost); + fstrcpy(dest,desthost); + p = strchr(dest,'.'); if (p) *p = 0; @@ -302,11 +303,11 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); } - strcpy(dev,"A:"); + pstrcpy(dev,"A:"); if (connect_as_printer) - strcpy(dev,"LPT1:"); + pstrcpy(dev,"LPT1:"); if (connect_as_ipc) - strcpy(dev,"IPC"); + pstrcpy(dev,"IPC"); if (start_session && !cli_send_session_request(inbuf,outbuf)) @@ -438,7 +439,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu { fstring pword; int passlen = strlen(pass)+1; - strcpy(pword,pass); + fstrcpy(pword,pass); #ifdef SMB_PASSWD if (doencrypt && *pass) { @@ -451,7 +452,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu #endif /* if in share level security then don't send a password now */ - if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} + if (!(sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} /* send a session setup command */ bzero(outbuf,smb_size); @@ -557,7 +558,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu { int passlen = strlen(pass)+1; fstring pword; - strcpy(pword,pass); + fstrcpy(pword,pass); #ifdef SMB_PASSWD if (doencrypt && *pass) { @@ -568,7 +569,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu /* if in user level security then don't send a password now */ if ((sec_mode & 1)) { - strcpy(pword, ""); passlen=1; + fstrcpy(pword, ""); passlen=1; } set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); @@ -817,9 +818,9 @@ BOOL cli_open_sockets(int port) } else { - strcpy(service2,service); + pstrcpy(service2,service); host = strtok(service2,"\\/"); - strcpy(desthost,host); + pstrcpy(desthost,host); } DEBUG(5,("Opening sockets\n")); diff --git a/source/include/local.h b/source/include/local.h index fc589d7ac0d..9548bf74b6b 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -42,6 +42,8 @@ #define WORDMAX 0xFFFF +/* the maximum password length before we declare a likely attack */ +#define MAX_PASSWORD_LENGTH 200 /* separators for lists */ #define LIST_SEP " \t,;:\n\r" diff --git a/source/include/proto.h b/source/include/proto.h index 01afb7cad95..ffa2f251cca 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -976,6 +976,8 @@ void file_unlock(int fd); BOOL is_myname(const char *s); void set_remote_arch(enum remote_arch_types type); enum remote_arch_types get_remote_arch(); +void fstrcpy(char *dest, char *src); +void pstrcpy(char *dest, char *src); /*The following definitions come from vt_mode.c */ diff --git a/source/lib/system.c b/source/lib/system.c index 447a4f88aca..df24691512f 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -311,8 +311,8 @@ int sys_rename(char *from, char *to) int rcode; pstring zfrom, zto; - strcpy (zfrom, dos_to_unix (from, False)); - strcpy (zto, dos_to_unix (to, False)); + pstrcpy (zfrom, dos_to_unix (from, False)); + pstrcpy (zto, dos_to_unix (to, False)); rcode = rename (zfrom, zto); if (errno == EXDEV) diff --git a/source/lib/time.c b/source/lib/time.c index d16552b61e2..4f688d2214a 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -469,12 +469,12 @@ BOOL set_filetime(char *fname,time_t mtime) ****************************************************************************/ char *timestring(void ) { - static char TimeBuf[100]; + static fstring TimeBuf; time_t t = time(NULL); struct tm *tm = LocalTime(&t); #ifdef NO_STRFTIME - strcpy(TimeBuf, asctime(tm)); + fstrcpy(TimeBuf, asctime(tm)); #elif defined(CLIX) || defined(CONVEX) strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",tm); #elif defined(AMPM) diff --git a/source/lib/username.c b/source/lib/username.c index b8d152c83fd..46b8f4cb332 100644 --- a/source/lib/username.c +++ b/source/lib/username.c @@ -62,7 +62,7 @@ void map_username(char *user) if (strequal(user,last_from)) { DEBUG(3,("Mapped user %s to %s\n",user,last_to)); - strcpy(user,last_to); + fstrcpy(user,last_to); return; } @@ -173,7 +173,7 @@ struct passwd *Get_Pwnam(char *user,BOOL allow_change) if (ret) return(ret); if (allow_change) - strcpy(user,user2); + fstrcpy(user,user2); return(NULL); } diff --git a/source/lib/util.c b/source/lib/util.c index 7f922def7e3..0c4999c789c 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -1079,7 +1079,7 @@ void unix_format(char *fname) if (*fname == '/') { - strcpy(namecopy,fname); + pstrcpy(namecopy,fname); strcpy(fname,"."); strcat(fname,namecopy); } @@ -1290,7 +1290,7 @@ void dos_clean_name(char *s) pstring s1; *p = 0; - strcpy(s1,p+3); + pstrcpy(s1,p+3); if ((p=strrchr(s,'\\')) != NULL) *p = 0; @@ -1328,7 +1328,7 @@ void unix_clean_name(char *s) pstring s1; *p = 0; - strcpy(s1,p+3); + pstrcpy(s1,p+3); if ((p=strrchr(s,'/')) != NULL) *p = 0; @@ -1355,7 +1355,7 @@ int ChDir(char *path) DEBUG(3,("chdir to %s\n",path)); res = sys_chdir(path); if (!res) - strcpy(LastDir,path); + pstrcpy(LastDir,path); return(res); } @@ -1515,7 +1515,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) /* remove any double slashes */ string_sub(s,"//","/"); - strcpy(basename,s); + pstrcpy(basename,s); p = strrchr(basename,'/'); if (!p) @@ -1585,12 +1585,12 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) if (relative) { if (newname[l] == '/') - strcpy(s,newname + l + 1); + pstrcpy(s,newname + l + 1); else - strcpy(s,newname+l); + pstrcpy(s,newname+l); } else - strcpy(s,newname); + pstrcpy(s,newname); } ChDir(wd); @@ -1614,10 +1614,10 @@ static void expand_one(char *Mask,int len) int lfill = (len+1) - strlen(Mask); int l1= (p1 - Mask); pstring tmp; - strcpy(tmp,Mask); + pstrcpy(tmp,Mask); memset(tmp+l1,'?',lfill); - strcpy(tmp + l1 + lfill,Mask + l1 + 1); - strcpy(Mask,tmp); + pstrcpy(tmp + l1 + lfill,Mask + l1 + 1); + pstrcpy(Mask,tmp); } } @@ -1641,20 +1641,20 @@ void expand_mask(char *Mask,BOOL doext) filename_dos(Mask,filepart); - strcpy(mbeg,filepart); + pstrcpy(mbeg,filepart); if ((p1 = strchr(mbeg,'.')) != NULL) { hasdot = True; *p1 = 0; p1++; - strcpy(mext,p1); + pstrcpy(mext,p1); } else { strcpy(mext,""); if (strlen(mbeg) > 8) { - strcpy(mext,mbeg + 8); + pstrcpy(mext,mbeg + 8); mbeg[8] = 0; } } @@ -1672,7 +1672,7 @@ void expand_mask(char *Mask,BOOL doext) if (*mext) expand_one(mext,3); - strcpy(Mask,dirpart); + pstrcpy(Mask,dirpart); if (*dirpart || absolute) strcat(Mask,"\\"); strcat(Mask,mbeg); strcat(Mask,"."); @@ -1773,7 +1773,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode char *p; pstring mask2; - strcpy(mask2,mask); + pstrcpy(mask2,mask); if ((mode & aDIR) != 0) size = 0; @@ -2421,7 +2421,12 @@ BOOL string_init(char **dest,char *src) } else { - *dest = (char *)malloc(l+1); + (*dest) = (char *)malloc(l+1); + if ((*dest) == NULL) { + DEBUG(0,("Out of memory in string_init\n")); + return False; + } + strcpy(*dest,src); } return(True); @@ -2593,25 +2598,25 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); if (trans2) { - strcpy(ebase,p1); - strcpy(sbase,p2); + fstrcpy(ebase,p1); + fstrcpy(sbase,p2); } else { if ((p=strrchr(p1,'.'))) { *p = 0; - strcpy(ebase,p1); - strcpy(eext,p+1); + fstrcpy(ebase,p1); + fstrcpy(eext,p+1); } else { - strcpy(ebase,p1); + fstrcpy(ebase,p1); eext[0] = 0; } if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) { *p = 0; - strcpy(sbase,p2); - strcpy(sext,p+1); + fstrcpy(sbase,p2); + fstrcpy(sext,p+1); } else { - strcpy(sbase,p2); - strcpy(sext,""); + fstrcpy(sbase,p2); + fstrcpy(sext,""); } } @@ -2927,7 +2932,7 @@ BOOL get_myname(char *my_name,struct in_addr *ip) char *p = strchr(hostname,'.'); if (p) *p = 0; - strcpy(my_name,hostname); + fstrcpy(my_name,hostname); } if (ip) @@ -3295,7 +3300,7 @@ char *client_addr(void) return addr_buf; } - strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); + fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); global_client_addr_done = True; return addr_buf; @@ -3552,7 +3557,7 @@ char *readdirname(void *p) { static pstring buf; - strcpy(buf, dname); + pstrcpy(buf, dname); unix_to_dos(buf, True); dname = buf; } @@ -3907,3 +3912,54 @@ enum remote_arch_types get_remote_arch() { return ra_type; } + + +/******************************************************************* +safe string copy into a fstring +********************************************************************/ +void fstrcpy(char *dest, char *src) +{ + int maxlength = sizeof(fstring) - 1; + if (!dest) { + DEBUG(0,("ERROR: NULL dest in fstrcpy\n")); + return; + } + + if (!src) { + *dest = 0; + return; + } + + while (maxlength-- && *src) + *dest++ = *src++; + *dest = 0; + if (*src) { + DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n", + strlen(src))); + } +} + +/******************************************************************* +safe string copy into a pstring +********************************************************************/ +void pstrcpy(char *dest, char *src) +{ + int maxlength = sizeof(pstring) - 1; + if (!dest) { + DEBUG(0,("ERROR: NULL dest in pstrcpy\n")); + return; + } + + if (!src) { + *dest = 0; + return; + } + + while (maxlength-- && *src) + *dest++ = *src++; + *dest = 0; + if (*src) { + DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n", + strlen(src))); + } +} diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index bc967bdacb4..29b54a708bc 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -616,10 +616,10 @@ static int build_dgram(char *buf,struct packet_struct *p) ******************************************************************/ void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope) { - strcpy(n->name,name); + fstrcpy(n->name,name); strupper(n->name); n->name_type = type; - strcpy(n->scope,this_scope); + fstrcpy(n->scope,this_scope); } diff --git a/source/locking/locking.c b/source/locking/locking.c index 760d21a05d8..c2a06cac75c 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -108,7 +108,7 @@ BOOL start_share_mode_mgmt(void) { pstring shmem_file_name; - strcpy(shmem_file_name,lp_lockdir()); + pstrcpy(shmem_file_name,lp_lockdir()); if (!directory_exist(shmem_file_name,NULL)) mkdir(shmem_file_name,0755); trim_string(shmem_file_name,"","/"); diff --git a/source/nameannounce.c b/source/nameannounce.c index 684ef412581..84e3ad3fa77 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -174,11 +174,11 @@ void do_announce_host(int command, SSVAL(p,27,BROWSER_ELECTION_VERSION); SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */ - strcpy(p+31,server_comment); + pstrcpy(p+31,server_comment); p += 31; p = skip_string(p,1); - debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); /* send the announcement */ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf, diff --git a/source/namedbname.c b/source/namedbname.c index a45a749f140..51571d786a8 100644 --- a/source/namedbname.c +++ b/source/namedbname.c @@ -226,11 +226,11 @@ void dump_names(void) if(lp_wins_support() == False || wins_subnet == 0) return; - strcpy(fname,lp_lockdir()); + fstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); strcat(fname,"/"); strcat(fname,WINS_LIST); - strcpy(fnamenew,fname); + fstrcpy(fnamenew,fname); strcat(fnamenew,"."); f = fopen(fnamenew,"w"); @@ -306,7 +306,7 @@ void load_netbios_names(void) if (!d) return; - strcpy(fname,lp_lockdir()); + fstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); strcat(fname,"/"); strcat(fname,WINS_LIST); @@ -366,7 +366,7 @@ void load_netbios_names(void) nb_flags_str[strlen(nb_flags_str)-1] = '\0'; /* netbios name. # divides the name from the type (hex): netbios#xx */ - strcpy(name,name_str); + pstrcpy(name,name_str); p = strchr(name,'#'); diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c index 6364ebba543..4f0b647996d 100644 --- a/source/namedbsubnet.c +++ b/source/namedbsubnet.c @@ -308,11 +308,11 @@ void write_browse_list(time_t t) dump_names(); dump_workgroups(); - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); strcat(fname,"/"); strcat(fname,SERVER_LIST); - strcpy(fnamenew,fname); + pstrcpy(fnamenew,fname); strcat(fnamenew,"."); f = fopen(fnamenew,"w"); diff --git a/source/nameelect.c b/source/nameelect.c index 4666b22588c..5c156a312ed 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -182,7 +182,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion, SIVAL(p,1,criterion); SIVAL(p,5,timeup*1000); /* ms - despite the spec */ p += 13; - strcpy(p,name); + pstrcpy(p,name); strupper(p); p = skip_string(p,1); diff --git a/source/namelogon.c b/source/namelogon.c index 1c118c85418..1f57139d56a 100644 --- a/source/namelogon.c +++ b/source/namelogon.c @@ -74,7 +74,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) token = SVAL(tmp,3); reply_code = 0x6; - strcpy(reply_name,myname); + fstrcpy(reply_name,myname); strupper(reply_name); add_slashes = True; DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", @@ -87,11 +87,11 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) logname = skip_string(machine,1); token = SVAL(skip_string(logname,1),0); - strcpy(reply_name,lp_domain_controller()); + fstrcpy(reply_name,lp_domain_controller()); if (!*reply_name) { /* oo! no domain controller. must be us, then */ - strcpy(reply_name,myname); + fstrcpy(reply_name,myname); reply_code = 0xC; } else diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 925f975ffef..3f0279908da 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -121,7 +121,7 @@ static BOOL dump_core(void) { char *p; pstring dname; - strcpy(dname,debugf); + pstrcpy(dname,debugf); if ((p=strrchr(dname,'/'))) *p=0; strcat(dname,"/corefiles"); mkdir(dname,0700); @@ -188,10 +188,10 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; - strcpy(fname,lp_configfile()); + pstrcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - strcpy(servicesf,fname); + pstrcpy(servicesf,fname); test = False; } } @@ -276,7 +276,7 @@ static void load_hosts_file(char *fname) if (strchr(flags,'M')) { source = SELF; - strcpy(myname,name); + pstrcpy(myname,name); } ipaddr = *interpret_addr2(ip); @@ -371,7 +371,7 @@ static BOOL init_structs() pstring nbname; if (! *myname) { - strcpy(myname,myhostname); + fstrcpy(myname,myhostname); p = strchr(myname,'.'); if (p) *p = 0; } @@ -422,7 +422,7 @@ static BOOL init_structs() /* Terminate name list */ my_netbios_names[namecount++]=NULL; - strcpy(local_machine,myname); + fstrcpy(local_machine,myname); trim_string(local_machine," "," "); p = strchr(local_machine,' '); if (p) @@ -501,7 +501,7 @@ static void usage(char *pname) strncpy(pidFile, optarg, sizeof(pidFile)); break; case 's': - strcpy(servicesf,optarg); + pstrcpy(servicesf,optarg); break; case 'N': case 'B': @@ -511,17 +511,17 @@ static void usage(char *pname) DEBUG(0,("Obsolete option '%c' used\n",opt)); break; case 'H': - strcpy(host_file,optarg); + pstrcpy(host_file,optarg); break; case 'n': - strcpy(myname,optarg); + pstrcpy(myname,optarg); strupper(myname); break; case 'l': sprintf(debugf,"%s.nmb",optarg); break; case 'i': - strcpy(scope,optarg); + pstrcpy(scope,optarg); strupper(scope); break; case 'D': @@ -564,7 +564,7 @@ static void usage(char *pname) reload_services(True); - strcpy(myworkgroup, lp_workgroup()); + pstrcpy(myworkgroup, lp_workgroup()); if (strequal(myworkgroup,"*")) { DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); diff --git a/source/nmbsync.c b/source/nmbsync.c index f2161f631af..de2f7aa00f1 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -82,7 +82,7 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv SIVAL(p,0,servertype); p += 4; - strcpy(p, work->work_group); + pstrcpy(p, work->work_group); p = skip_string(p,1); if (cli_call_api(PTR_DIFF(p,param),0, 8,BUFFER_SIZE - SAFETY_MARGIN, @@ -162,7 +162,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, name, work->work_group, inet_ntoa(ip))); strcpy(workgroup,work->work_group); - strcpy(desthost,name); + fstrcpy(desthost,name); dest_ip = ip; if (zero_ip(dest_ip)) return; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index ad9bf83886d..510a661dc39 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -1382,7 +1382,7 @@ static void add_to_file_list(char *fname) { pstring n2; - strcpy(n2,fname); + pstrcpy(n2,fname); standard_sub_basic(n2); f->modtime = file_modtime(n2); } @@ -1402,7 +1402,7 @@ BOOL lp_file_list_changed(void) pstring n2; time_t mod_time; - strcpy(n2,f->name); + pstrcpy(n2,f->name); standard_sub_basic(n2); DEBUG(6,("file %s -> %s last mod_time: %s\n", @@ -1532,7 +1532,7 @@ handle the include operation static BOOL handle_include(char *pszParmValue,char **ptr) { pstring fname; - strcpy(fname,pszParmValue); + pstrcpy(fname,pszParmValue); add_to_file_list(fname); @@ -2025,7 +2025,7 @@ BOOL lp_load(char *pszFname,BOOL global_only) init_globals(); - strcpy(n2,pszFname); + pstrcpy(n2,pszFname); standard_sub_basic(n2); /* We get sections first, so have to start 'behind' to make up */ diff --git a/source/printing/pcap.c b/source/printing/pcap.c index 549ebcd70df..65195ab1af6 100644 --- a/source/printing/pcap.c +++ b/source/printing/pcap.c @@ -358,8 +358,8 @@ void pcap_printer_fn(void (*fn)()) if (strlen(p) <= 8 && strlen(p)>strlen(name) && !has_punctuation) { - if (!*comment) strcpy(comment,name); - strcpy(name,p); + if (!*comment) pstrcpy(comment,name); + pstrcpy(name,p); continue; } diff --git a/source/printing/printing.c b/source/printing/printing.c index c83d2169891..51fd3a992eb 100644 --- a/source/printing/printing.c +++ b/source/printing/printing.c @@ -85,7 +85,7 @@ static char *build_print_command(int cnum, char *command, char *syscmd, char *fi strcat(filename,filename1); } else - strcpy(filename,filename1); + pstrcpy(filename,filename1); string_sub(syscmd, "%s", filename); } @@ -258,7 +258,7 @@ static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first) if (p) { strcpy(tmp,p+1); - strcpy(tok[FILETOK],tmp); + fstrcpy(tok[FILETOK],tmp); } } @@ -404,8 +404,8 @@ A long spool-path will just waste significant chars of the file name. char *p = strrchr(tok[LPRNG_FILETOK],'/'); if (p) { - strcpy(tmp,p+1); - strcpy(tok[LPRNG_FILETOK],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[LPRNG_FILETOK],tmp); } } @@ -472,8 +472,8 @@ static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) char *p = strrchr(tok[2],'/'); if (p) { - strcpy(tmp,p+1); - strcpy(tok[2],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[2],tmp); } } @@ -506,8 +506,8 @@ static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) char *p = strrchr(tok[4],'/'); if (p) { - strcpy(tmp,p+1); - strcpy(tok[4],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[4],tmp); } } @@ -666,8 +666,8 @@ static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first) if ((p=strchr(tok[2],'!'))) { string tmp; - strcpy(tmp,p+1); - strcpy(tok[2],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[2],tmp); } @@ -731,8 +731,8 @@ static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first) char *p = strrchr(tok[6],'/'); if (p) { - strcpy(tmp,p+1); - strcpy(tok[6],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[6],tmp); } } @@ -795,8 +795,8 @@ static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first) char *p = strrchr(tok[6],'/'); if (p) { - strcpy(tmp,p+1); - strcpy(tok[6],tmp); + fstrcpy(tmp,p+1); + fstrcpy(tok[6],tmp); } } @@ -863,7 +863,7 @@ static BOOL parse_lpq_entry(int snum,char *line, /* change guest entries to the current logged in user to make them appear deletable to windows */ if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum))) - strcpy(buf->user,sesssetup_user); + pstrcpy(buf->user,sesssetup_user); } #endif @@ -940,7 +940,7 @@ int get_printqueue(int snum,int cnum,print_queue_struct **queue, return(0); } - strcpy(syscmd,lpq_command); + pstrcpy(syscmd,lpq_command); string_sub(syscmd,"%p",printername); standard_sub(cnum,syscmd); @@ -1031,7 +1031,7 @@ void del_printqueue(int cnum,int snum,int jobid) sprintf(jobstr,"%d",jobid); - strcpy(syscmd,lprm_command); + pstrcpy(syscmd,lprm_command); string_sub(syscmd,"%p",printername); string_sub(syscmd,"%j",jobstr); standard_sub(cnum,syscmd); @@ -1069,7 +1069,7 @@ void status_printjob(int cnum,int snum,int jobid,int status) sprintf(jobstr,"%d",jobid); - strcpy(syscmd,lpstatus_command); + pstrcpy(syscmd,lpstatus_command); string_sub(syscmd,"%p",printername); string_sub(syscmd,"%j",jobstr); standard_sub(cnum,syscmd); diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index 6063f2aac8a..bed81138b24 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -212,8 +212,8 @@ static int expect(int master,char *expected,char *buf) { pstring s1,s2; - strcpy(s1,buf); - strcpy(s2,expected); + pstrcpy(s1,buf); + pstrcpy(s2,expected); if (do_match(s1, s2, False)) return(True); } @@ -364,11 +364,11 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass) } #if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT)) - strcpy(passwordprogram,PASSWD_PROGRAM); - strcpy(chatsequence,PASSWD_CHAT); + pstrcpy(passwordprogram,PASSWD_PROGRAM); + pstrcpy(chatsequence,PASSWD_CHAT); #else - strcpy(passwordprogram,lp_passwd_program()); - strcpy(chatsequence,lp_passwd_chat()); + pstrcpy(passwordprogram,lp_passwd_program()); + pstrcpy(chatsequence,lp_passwd_chat()); #endif if (!*chatsequence) { diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 06ee6ae8ed7..567bc14424e 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -461,7 +461,7 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo matched = False; - strcpy(filename,dname); + pstrcpy(filename,dname); if ((strcmp(filename,mask) == 0) || (name_map_mangle(filename,True,SNUM(cnum)) && diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 55e293d7ffd..9aaf03e6c4f 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -774,7 +774,7 @@ static int get_server_info(uint32 servertype, pstring line; BOOL local_list_only; - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); strcat(fname,"/"); strcat(fname,SERVER_LIST); @@ -1363,7 +1363,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, fstring user; fstring pass1,pass2; - strcpy(user,p); + fstrcpy(user,p); p = skip_string(p,1); @@ -1698,14 +1698,14 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, pstring comment; uint32 servertype= lp_default_server_announce(); - strcpy(comment,lp_serverstring()); + pstrcpy(comment,lp_serverstring()); if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) { for (i=0;i 0) { @@ -2043,9 +2043,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, strcpy(p2,"UserComment"); p2 = skip_string(p2,1); - /* EEK! the cifsrap.txt doesn't have this in!!!! */ + /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,vuser->real_name); /* simeon */ p2 = skip_string(p2,1); } @@ -2062,7 +2062,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, else { #if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); + strcpy(p2, vuser->home_share); #else strcpy(p2,"\\\\%L\\%U"); #endif @@ -2461,7 +2461,8 @@ static void fill_printdest_info(int cnum, int snum, int uLevel, struct pack_desc* desc) { char buf[100]; - strcpy(buf,SERVICE(snum)); + strncpy(buf,SERVICE(snum),sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; strupper(buf); if (uLevel <= 1) { PACKS(desc,"B9",buf); /* szName */ @@ -3018,7 +3019,11 @@ int reply_trans(char *inbuf,char *outbuf) int dsoff = SVAL(inbuf,smb_vwv12); int suwcnt = CVAL(inbuf,smb_vwv13); - StrnCpy(name,smb_buf(inbuf),sizeof(name)-1); + fstrcpy(name,smb_buf(inbuf)); + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } if (tdscnt) { @@ -3080,6 +3085,10 @@ int reply_trans(char *inbuf,char *outbuf) pscnt += pcnt; dscnt += dcnt; + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters\n"); + } + if (pcnt) memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); if (dcnt) diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index a08402a85ea..a964f4a5c73 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -269,7 +269,7 @@ BOOL check_mangled_stack(char *s) } if (check_extension && !strchr(mangled_stack[i],'.')) { - strcpy(tmpname,mangled_stack[i]); + pstrcpy(tmpname,mangled_stack[i]); strcat(tmpname,extension); mangle_name_83(tmpname); if (strequal(tmpname,s)) @@ -303,7 +303,7 @@ static char *map_filename(char *s, /* This is null terminated */ pstring pat; StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */ - strcpy(matching_bit,""); /* Match but no star gets this. */ + pstrcpy(matching_bit,""); /* Match but no star gets this. */ pp = pat; /* Initialise the pointers. */ sp = s; if ((len == 1) && (*pattern == '*')) { @@ -442,7 +442,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) continue; /* Always check for the end. */ } if (*end == '*') { - strcpy(np, match_string); + pstrcpy(np, match_string); np += strlen(match_string); end++; /* Skip the '*' */ while ((*end) /* Not the end of string. */ @@ -456,7 +456,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap) } *np++ = '\0'; /* NULL terminate it. */ DEBUG(5,("End of second in pair '%s'\n", end)); - strcpy(s, new_string); /* Substitute with the new name. */ + pstrcpy(s, new_string); /* Substitute with the new name. */ DEBUG(5,("s is now '%s'\n", s)); } start = end; /* Skip a bit which cannot be wanted */ diff --git a/source/smbd/message.c b/source/smbd/message.c index 93a2d9d850a..64253932abb 100644 --- a/source/smbd/message.c +++ b/source/smbd/message.c @@ -54,7 +54,7 @@ static void msg_deliver(void) /* put it in a temporary file */ sprintf(s,"%s/msg.XXXXXX",tmpdir()); - strcpy(name,(char *)mktemp(s)); + fstrcpy(name,(char *)mktemp(s)); fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); if (fd == -1) { @@ -74,7 +74,7 @@ static void msg_deliver(void) /* run the command */ if (*lp_msg_command()) { - strcpy(s,lp_msg_command()); + pstrcpy(s,lp_msg_command()); string_sub(s,"%s",name); string_sub(s,"%f",msgfrom); string_sub(s,"%t",msgto); @@ -108,8 +108,8 @@ int reply_sends(char *inbuf,char *outbuf) dest = skip_string(orig,1)+1; msg = skip_string(dest,1)+1; - strcpy(msgfrom,orig); - strcpy(msgto,dest); + fstrcpy(msgfrom,orig); + fstrcpy(msgto,dest); len = SVAL(msg,0); len = MIN(len,1600-msgpos); @@ -143,10 +143,10 @@ int reply_sendstrt(char *inbuf,char *outbuf) orig = smb_buf(inbuf)+1; dest = skip_string(orig,1)+1; - strcpy(msgfrom,orig); - strcpy(msgto,dest); + fstrcpy(msgfrom,orig); + fstrcpy(msgto,dest); - DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),orig,dest)); + DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),msgfrom,msgto)); return(outsize); } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index afab7e1d911..feb8d91a5b0 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -87,7 +87,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL bad_path = False; /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); + pstrcpy(fname,smb_buf(inbuf)); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ @@ -98,7 +98,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Opening pipe %s.\n", fname)); /* Strip \PIPE\ off the name. */ - strcpy(fname,smb_buf(inbuf) + PIPELEN); + pstrcpy(fname,smb_buf(inbuf) + PIPELEN); /* See if it is one we want to handle. */ for( i = 0; known_pipes[i] ; i++ ) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index a15185146da..4235e7725e9 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -48,6 +48,18 @@ a packet to ensure chaining works correctly */ #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) +/**************************************************************************** +report a possible attack via the password buffer overflow bug +****************************************************************************/ +static void overflow_attack(int len) +{ + DEBUG(0,("ERROR: Invalid password length %d\n", len)); + DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n")); + DEBUG(0,("Attack was from IP=%s\n", client_addr())); + exit_server("possible attack"); +} + + /**************************************************************************** reply to an special message ****************************************************************************/ @@ -69,22 +81,22 @@ int reply_special(char *inbuf,char *outbuf) case 0x81: /* session request */ CVAL(outbuf,0) = 0x82; CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) { - DEBUG(0,("Invalid name length in session request\n")); - return(0); - } + if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { + DEBUG(0,("Invalid name length in session request\n")); + return(0); + } name_extract(inbuf,4,name1); name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - strcpy(remote_machine,name2); + fstrcpy(remote_machine,name2); trim_string(remote_machine," "," "); p = strchr(remote_machine,' '); strlower(remote_machine); if (p) *p = 0; - strcpy(local_machine,name1); + fstrcpy(local_machine,name1); trim_string(local_machine," "," "); p = strchr(local_machine,' '); strlower(local_machine); @@ -160,25 +172,25 @@ static void parse_connect(char *p,char *service,char *user, p2 = strrchr(p,'\\'); if (p2 == NULL) - strcpy(service,p); + fstrcpy(service,p); else - strcpy(service,p2+1); + fstrcpy(service,p2+1); p += strlen(p) + 2; - strcpy(password,p); + fstrcpy(password,p); *pwlen = strlen(password); p += strlen(p) + 2; - strcpy(dev,p); + fstrcpy(dev,p); *user = 0; p = strchr(service,'%'); if (p != NULL) { *p = 0; - strcpy(user,p+1); + fstrcpy(user,p+1); } } @@ -238,6 +250,10 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* we might have to close an old one */ if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); + + if (passlen > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen); + } { char *path; @@ -252,18 +268,17 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) passlen = strlen(password); } - DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); - strcpy(service,path+2); + fstrcpy(service,path+2); p = strchr(service,'\\'); if (!p) return(ERROR(ERRSRV,ERRinvnetname)); *p = 0; - strcpy(service,p+1); + fstrcpy(service,p+1); p = strchr(service,'%'); if (p) { *p++ = 0; - strcpy(user,p); + fstrcpy(user,p); } StrnCpy(devicename,path + strlen(path) + 1,6); DEBUG(4,("Got device type %s\n",devicename)); @@ -372,11 +387,15 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); + if (smb_apasslen > MAX_PASSWORD_LENGTH) + overflow_attack(smb_apasslen); + memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); + pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - if (lp_security() != SEC_SERVER && !doencrypt) - smb_apasslen = strlen(smb_apasswd); + if (lp_security() != SEC_SERVER && !doencrypt) { + smb_apasslen = strlen(smb_apasswd); + } } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); uint16 passlen2 = SVAL(inbuf,smb_vwv8); @@ -401,6 +420,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; + if (passlen1 > MAX_PASSWORD_LENGTH) { + overflow_attack(passlen1); + } + + passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); + passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ smb_apasslen = passlen1; @@ -438,7 +464,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } p += passlen1 + passlen2; - strcpy(user,p); p = skip_string(p,1); + fstrcpy(user,p); p = skip_string(p,1); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", p,skip_string(p,1),skip_string(p,2))); } @@ -591,7 +617,7 @@ int reply_chkpth(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); unix_convert(name,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -639,7 +665,7 @@ int reply_getatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); /* dos smetimes asks for a stat of "" - it returns a "hidden directory" @@ -714,7 +740,7 @@ int reply_setatr(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(fname,smb_buf(inbuf) + 1); + pstrcpy(fname,smb_buf(inbuf) + 1); unix_convert(fname,cnum,0,&bad_path); mode = SVAL(inbuf,smb_vwv0); @@ -825,8 +851,8 @@ int reply_search(char *inbuf,char *outbuf) { pstring dir2; - strcpy(directory,smb_buf(inbuf)+1); - strcpy(dir2,smb_buf(inbuf)+1); + pstrcpy(directory,smb_buf(inbuf)+1); + pstrcpy(dir2,smb_buf(inbuf)+1); unix_convert(directory,cnum,0,&bad_path); unix_format(dir2); @@ -842,7 +868,7 @@ int reply_search(char *inbuf,char *outbuf) else { *p = 0; - strcpy(mask,p+1); + pstrcpy(mask,p+1); } p = strrchr(directory,'/'); @@ -876,7 +902,7 @@ int reply_search(char *inbuf,char *outbuf) if ((p = strrchr(mask,' '))) { fstring ext; - strcpy(ext,p+1); + fstrcpy(ext,p+1); *p = 0; trim_string(mask,NULL," "); strcat(mask,"."); @@ -898,7 +924,7 @@ int reply_search(char *inbuf,char *outbuf) if (!strchr(mask,'.') && strlen(mask)>8) { fstring tmp; - strcpy(tmp,&mask[8]); + fstrcpy(tmp,&mask[8]); mask[8] = '.'; mask[9] = 0; strcat(mask,tmp); @@ -1078,7 +1104,7 @@ int reply_open(char *inbuf,char *outbuf) share_mode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1168,7 +1194,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); + pstrcpy(fname,smb_buf(inbuf)); unix_convert(fname,cnum,0,&bad_path); fnum = find_free_file(); @@ -1281,7 +1307,7 @@ int reply_mknew(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); unix_convert(fname,cnum,0,&bad_path); if (createmode & aVOLID) @@ -1359,7 +1385,8 @@ int reply_ctemp(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); - sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); + pstrcpy(fname,smb_buf(inbuf)+1); + strcat(fname,"/TMXXXXXX"); unix_convert(fname,cnum,0,&bad_path); unixmode = unix_mode(cnum,createmode); @@ -1455,7 +1482,7 @@ int reply_unlink(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); dirtype = SVAL(inbuf,smb_vwv0); - strcpy(name,smb_buf(inbuf) + 1); + pstrcpy(name,smb_buf(inbuf) + 1); DEBUG(3,("reply_unlink : %s\n",name)); @@ -1503,7 +1530,7 @@ int reply_unlink(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -2381,7 +2408,7 @@ int reply_printopen(char *inbuf,char *outbuf) { pstring s; char *p; - StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1); + pstrcpy(s,smb_buf(inbuf)+1); p = s; while (*p) { @@ -2583,7 +2610,7 @@ int reply_mkdir(char *inbuf,char *outbuf) int outsize,ret= -1; BOOL bad_path = False; - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); cnum = SVAL(inbuf,smb_tid); unix_convert(directory,cnum,0,&bad_path); @@ -2620,7 +2647,7 @@ int reply_rmdir(char *inbuf,char *outbuf) BOOL bad_path = False; cnum = SVAL(inbuf,smb_tid); - strcpy(directory,smb_buf(inbuf) + 1); + pstrcpy(directory,smb_buf(inbuf) + 1); unix_convert(directory,cnum,0,&bad_path); if (check_name(directory,cnum)) @@ -2668,7 +2695,7 @@ int reply_rmdir(char *inbuf,char *outbuf) errno = ENOMEM; break; } - strcpy(fullname, directory); + pstrcpy(fullname, directory); strcat(fullname, "/"); strcat(fullname, dname); @@ -2730,21 +2757,21 @@ static BOOL resolve_wildcards(char *name1,char *name2) if (!name1 || !name2) return(False); - strcpy(root1,name1); - strcpy(root2,name2); + fstrcpy(root1,name1); + fstrcpy(root2,name2); p = strrchr(root1,'.'); if (p) { *p = 0; - strcpy(ext1,p+1); + fstrcpy(ext1,p+1); } else { - strcpy(ext1,""); + fstrcpy(ext1,""); } p = strrchr(root2,'.'); if (p) { *p = 0; - strcpy(ext2,p+1); + fstrcpy(ext2,p+1); } else { - strcpy(ext2,""); + fstrcpy(ext2,""); } p = root1; @@ -2818,8 +2845,8 @@ int reply_mv(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf) + 1); - strcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); + pstrcpy(name,smb_buf(inbuf) + 1); + pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -2933,14 +2960,14 @@ int reply_mv(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; error = ERRnoaccess; sprintf(fname,"%s/%s",directory,dname); if (!can_rename(fname,cnum)) continue; - strcpy(destname,newname); + pstrcpy(destname,newname); if (!resolve_wildcards(fname,destname)) continue; @@ -2986,7 +3013,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, int fnum1,fnum2; pstring dest; - strcpy(dest,dest1); + pstrcpy(dest,dest1); if (target_is_directory) { char *p = strrchr(src,'/'); if (p) @@ -3063,8 +3090,8 @@ int reply_copy(char *inbuf,char *outbuf) cnum = SVAL(inbuf,smb_tid); - strcpy(name,smb_buf(inbuf)); - strcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); + pstrcpy(name,smb_buf(inbuf)); + pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); @@ -3133,7 +3160,7 @@ int reply_copy(char *inbuf,char *outbuf) while ((dname = ReadDirName(dirptr))) { pstring fname; - strcpy(fname,dname); + pstrcpy(fname,dname); if(!mask_match(fname, mask, case_sensitive, False)) continue; @@ -3187,7 +3214,7 @@ int reply_setdir(char *inbuf,char *outbuf) if (!CAN_SETDIR(snum)) return(ERROR(ERRDOS,ERRnoaccess)); - strcpy(newdir,smb_buf(inbuf) + 1); + pstrcpy(newdir,smb_buf(inbuf) + 1); strlower(newdir); if (strlen(newdir) == 0) diff --git a/source/smbd/server.c b/source/smbd/server.c index d4407269f0b..2bc0e023158 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -393,7 +393,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) (strequal(dname,".") || strequal(dname,".."))) continue; - strcpy(name2,dname); + pstrcpy(name2,dname); if (!name_map_mangle(name2,False,SNUM(cnum))) continue; if ((mangled && mangled_equal(name,name2)) @@ -539,7 +539,7 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa /* remember the rest of the pathname so it can be restored later */ - if (end) strcpy(rest,end+1); + if (end) pstrcpy(rest,end+1); /* try to find this part of the path in the directory */ if (strchr(start,'?') || strchr(start,'*') || @@ -1051,7 +1051,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct Files[fnum].fd_ptr = 0; errno = EPERM; - strcpy(fname,fname1); + pstrcpy(fname,fname1); /* check permissions */ if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) @@ -1180,7 +1180,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct pstring dname; int dum1,dum2,dum3; char *p; - strcpy(dname,fname); + pstrcpy(dname,fname); p = strrchr(dname,'/'); if (p) *p = 0; if (sys_disk_free(dname,&dum1,&dum2,&dum3) < @@ -1315,10 +1315,10 @@ static void check_magic(int fnum,int cnum) int ret; pstring magic_output; pstring fname; - strcpy(fname,Files[fnum].name); + pstrcpy(fname,Files[fnum].name); if (*lp_magicoutput(SNUM(cnum))) - strcpy(magic_output,lp_magicoutput(SNUM(cnum))); + pstrcpy(magic_output,lp_magicoutput(SNUM(cnum))); else sprintf(magic_output,"%s.out",fname); @@ -2280,10 +2280,10 @@ BOOL reload_services(BOOL test) if (lp_loaded()) { pstring fname; - strcpy(fname,lp_configfile()); + pstrcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) { - strcpy(servicesf,fname); + pstrcpy(servicesf,fname); test = False; } } @@ -2576,13 +2576,13 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { struct passwd *pass2; fstring fuser; - strcpy(fuser,lp_force_user(snum)); + fstrcpy(fuser,lp_force_user(snum)); pass2 = (struct passwd *)Get_Pwnam(fuser,True); if (pass2) { pcon->uid = pass2->pw_uid; string_set(&pcon->user,fuser); - strcpy(user,fuser); + fstrcpy(user,fuser); pcon->force_user = True; DEBUG(3,("Forced user %s\n",fuser)); } @@ -2592,7 +2592,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de { pstring s; - strcpy(s,lp_pathname(snum)); + pstrcpy(s,lp_pathname(snum)); standard_sub(cnum,s); string_set(&pcon->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); @@ -2628,7 +2628,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (*lp_rootpreexec(SNUM(cnum))) { pstring cmd; - strcpy(cmd,lp_rootpreexec(SNUM(cnum))); + pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); standard_sub(cnum,cmd); DEBUG(5,("cmd=%s\n",cmd)); smbrun(cmd,NULL,False); @@ -2668,7 +2668,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* resolve any soft links early */ { pstring s; - strcpy(s,pcon->connectpath); + pstrcpy(s,pcon->connectpath); GetWd(s); string_set(&pcon->connectpath,s); ChDir(pcon->connectpath); @@ -2682,7 +2682,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de if (*lp_preexec(SNUM(cnum))) { pstring cmd; - strcpy(cmd,lp_preexec(SNUM(cnum))); + pstrcpy(cmd,lp_preexec(SNUM(cnum))); standard_sub(cnum,cmd); smbrun(cmd,NULL,False); } @@ -3153,7 +3153,7 @@ static int reply_negprot(char *inbuf,char *outbuf) SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { extern fstring remote_proto; - strcpy(remote_proto,supported_protocols[protocol].short_name); + fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); outsize = supported_protocols[protocol].proto_reply_fn(outbuf); DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); @@ -3272,7 +3272,7 @@ BOOL yield_connection(int cnum,char *name,int max_connections) bzero(&crec,sizeof(crec)); - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); standard_sub(cnum,fname); trim_string(fname,"","/"); @@ -3344,7 +3344,7 @@ BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections)); - strcpy(fname,lp_lockdir()); + pstrcpy(fname,lp_lockdir()); standard_sub(cnum,fname); trim_string(fname,"","/"); @@ -3440,7 +3440,7 @@ static BOOL dump_core(void) { char *p; pstring dname; - strcpy(dname,debugf); + pstrcpy(dname,debugf); if ((p=strrchr(dname,'/'))) *p=0; strcat(dname,"/corefiles"); mkdir(dname,0700); diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 19c1158658c..ecc8f5dbec7 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -306,10 +306,10 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if(p[1] == '\0') strcpy(mask,"*.*"); else - strcpy(mask, p+1); + pstrcpy(mask, p+1); } else - strcpy(mask, path_mask); + pstrcpy(mask, path_mask); while (!found) { @@ -327,7 +327,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l matched = False; - strcpy(fname,dname); + pstrcpy(fname,dname); if(mask_match(fname, mask, case_sensitive, True)) { @@ -338,7 +338,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l if (isrootdir && isdots) continue; - strcpy(pathreal,Connections[cnum].dirpath); + pstrcpy(pathreal,Connections[cnum].dirpath); if(needslash) strcat(pathreal,"/"); strcat(pathreal,dname); @@ -595,7 +595,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum return(ERROR(ERRDOS,ERRunknownlevel)); } - strcpy(directory, params + 12); /* Complete directory path with + pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */ DEBUG(5,("path=%s\n",directory)); @@ -1057,7 +1057,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, /* qpathinfo */ info_level = SVAL(params,0); fname = &fname1[0]; - strcpy(fname,¶ms[6]); + pstrcpy(fname,¶ms[6]); unix_convert(fname,cnum,0,&bad_path); if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); @@ -1163,7 +1163,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, case SMB_QUERY_FILE_ALT_NAME_INFO: data_size = 4 + l; SIVAL(pdata,0,l); - strcpy(pdata+4,fname); + pstrcpy(pdata+4,fname); break; case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: @@ -1197,7 +1197,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, pdata += 4; pdata += 4; /* alignment */ SIVAL(pdata,0,l); - strcpy(pdata+4,fname); + pstrcpy(pdata+4,fname); pdata += 4 + l; data_size = PTR_DIFF(pdata,(*ppdata)); break; @@ -1208,7 +1208,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, SIVAL(pdata,4,size); SIVAL(pdata,12,size); SIVAL(pdata,20,l); - strcpy(pdata+24,fname); + pstrcpy(pdata+24,fname); break; default: return(ERROR(ERRDOS,ERRunknownlevel)); @@ -1260,7 +1260,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, /* set path info */ info_level = SVAL(params,0); fname = fname1; - strcpy(fname,¶ms[6]); + pstrcpy(fname,¶ms[6]); unix_convert(fname,cnum,0,&bad_path); if(!check_name(fname, cnum)) { @@ -1435,7 +1435,7 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, if (!CAN_WRITE(cnum)) return(ERROR(ERRSRV,ERRaccess)); - strcpy(directory, ¶ms[4]); + pstrcpy(directory, ¶ms[4]); DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); @@ -1637,6 +1637,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); + if (num_params > total_params || num_data > total_data) + exit_server("invalid params in reply_trans2"); + memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); @@ -1664,6 +1667,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) total_data = SVAL(inbuf, smb_tdscnt); num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); + if (num_params_sofar > total_params || num_data_sofar > total_data) + exit_server("data overflow in trans2"); + memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); memcpy( &data[SVAL(inbuf, smb_sdsdisp)], diff --git a/source/smbd/vt_mode.c b/source/smbd/vt_mode.c index 0a4d50c217f..07558274a52 100644 --- a/source/smbd/vt_mode.c +++ b/source/smbd/vt_mode.c @@ -81,7 +81,7 @@ int VT_Start_utmp(void) setutent(); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_line, VT_Line); if((v = getutline(&u)) == NULL) { if(strncmp(VT_Line, "tty", 3) == 0) @@ -91,12 +91,12 @@ int VT_Start_utmp(void) else tt = VT_Line; - strcpy(u.ut_id, tt); + fstrcpy(u.ut_id, tt); u.ut_time = time((time_t*)0); } - strcpy(u.ut_user, "LOGIN"); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_user, "LOGIN"); + fstrcpy(u.ut_line, VT_Line); u.ut_pid = getpid(); u.ut_type = LOGIN_PROCESS; pututline(&u); @@ -118,10 +118,10 @@ int VT_Stop_utmp(void) if(VT_Line != NULL) { setutent(); - strcpy(u.ut_line, VT_Line); + fstrcpy(u.ut_line, VT_Line); if((v = getutline(&u)) != NULL) { - strcpy(v->ut_user, ""); + fstrcpy(v->ut_user, ""); v->ut_type = DEAD_PROCESS; v->ut_time = time((time_t*)0); pututline(v); diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c index 25c94dcd6a0..aebbc4292ca 100644 --- a/source/utils/nmblookup.c +++ b/source/utils/nmblookup.c @@ -122,7 +122,7 @@ int main(int argc,char *argv[]) got_bcast = True; break; case 'i': - strcpy(scope,optarg); + fstrcpy(scope,optarg); strupper(scope); break; case 'M': @@ -135,7 +135,7 @@ int main(int argc,char *argv[]) DEBUGLEVEL = atoi(optarg); break; case 's': - strcpy(servicesf, optarg); + pstrcpy(servicesf, optarg); break; case 'h': usage(); @@ -172,7 +172,7 @@ int main(int argc,char *argv[]) char *p; struct in_addr ip; - strcpy(lookup,argv[i]); + fstrcpy(lookup,argv[i]); if (find_master) { if (*lookup == '-') { -- cgit From 9d23bcbe5fac31017f5392478994df2d6a7e0d91 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 26 Sep 1997 12:47:59 +0000 Subject: preparing for release of 1.9.17p2 --- source/include/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/include/version.h b/source/include/version.h index afd20f5799d..76ccca122c6 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.17p1" +#define VERSION "1.9.17p2" -- cgit From 9f8164d73583c32908ec3b9a6ae6630e78723553 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 26 Sep 1997 13:09:36 +0000 Subject: add info about p2 release --- WHATSNEW.txt | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 500a4726bf2..fa3600d6c35 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,37 +1,31 @@ - WHATS NEW IN 1.9.17p1 - September 5 1997 - ======================================== + WHATS NEW IN 1.9.17p2 - September 26th 1997 + =========================================== -New stable patch release: Samba - version 1.9.17p1. ---------------------------------------------------- +Security fix release: Samba - version 1.9.17p2. +---------------------------------------------- -This is a patch release which superceedes the -last stable release of Samba, release 1.9.17. -This release fixes the few bugs that users reported -in the previous stable release (1.9.17). +This new stable release fixes a very important security hole in all +versions of Samba. -These bugfixes are : +The security hole allows a remote user to obtain root access on the +Samba server. A program which exploits this bug has been posted to the +internet. -Fix for DOS and Windows 95 clients having trouble -delting files on a Samba share in a DOS command line -environment. +The security hole is only known to affect Samba servers running on +Intel based hardware, and has only been demonstrated for Intel +Linux. It is likley that exploits for other architectures would be +very difficult but the possibility cannot be excluded completely. -Fixes to set the 'flag' bits correctly when talking to a -non-Samba WINS server. +This patch fixes the security hole for all platforms. -Fix for NT clients being dropped when using security=server. +This patch also adds a routine which will log a message when a user +attempts to take advantage of the security hole. -Fixes to the printer queue reporting code. - -Fix for the name map mangle bug (mangling .html -> .htm was -not working). - -If you are not affected by any of these problems then there -is no need to upgrade. - -The release notes from the previous stable release follow. +A number of other minor bugs have also been fixed in this release. The Samba Team. + -------------Previous release notes------------------------- New stable release of Samba - 1.9.17 -- cgit From 4488171706e774eba415cced394551f40677089f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 19:40:59 +0000 Subject: Fixed you're -> your text that some pedant complained about :-). Jeremy (jallison@whistle.com). --- source/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 4235e7725e9..6d7a3577c6c 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -54,7 +54,7 @@ report a possible attack via the password buffer overflow bug static void overflow_attack(int len) { DEBUG(0,("ERROR: Invalid password length %d\n", len)); - DEBUG(0,("you're machine may be under attack by a user exploiting an old bug\n")); + DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); DEBUG(0,("Attack was from IP=%s\n", client_addr())); exit_server("possible attack"); } -- cgit From 898302839f25c33a5bd2e47be950e7c486456589 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Sep 1997 21:43:44 +0000 Subject: Cause overflow attack to return an error code rather than terminate smbd. Terminating smbd allows a denial of service attack for multi-user NT servers. Jeremy (jallison@whistle.com) --- source/smbd/reply.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 6d7a3577c6c..d0beb285d73 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -56,7 +56,10 @@ static void overflow_attack(int len) DEBUG(0,("ERROR: Invalid password length %d\n", len)); DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); DEBUG(0,("Attack was from IP=%s\n", client_addr())); +/* Don't exit server here - it allows a possible denial of service attack. */ +#if 0 exit_server("possible attack"); +#endif } @@ -253,6 +256,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen > MAX_PASSWORD_LENGTH) { overflow_attack(passlen); + return(ERROR(ERRSRV,ERRbadpw)); } { @@ -388,7 +392,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); if (smb_apasslen > MAX_PASSWORD_LENGTH) + { overflow_attack(smb_apasslen); + return(ERROR(ERRSRV,ERRbadpw)); + } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); pstrcpy(user,smb_buf(inbuf)+smb_apasslen); @@ -422,6 +429,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 > MAX_PASSWORD_LENGTH) { overflow_attack(passlen1); + return(ERROR(ERRSRV,ERRbadpw)); } passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); -- cgit From 078da3c0f89641cf9cfa0109cd20a1626e6fdb14 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 27 Sep 1997 00:34:12 +0000 Subject: Put back changes to abort on overflow attack after conversation with Andrew. Jeremy (jallison@whistle.com) --- source/smbd/reply.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index d0beb285d73..f3a8ad22b8a 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -56,10 +56,7 @@ static void overflow_attack(int len) DEBUG(0,("ERROR: Invalid password length %d\n", len)); DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); DEBUG(0,("Attack was from IP=%s\n", client_addr())); -/* Don't exit server here - it allows a possible denial of service attack. */ -#if 0 exit_server("possible attack"); -#endif } @@ -256,7 +253,6 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen > MAX_PASSWORD_LENGTH) { overflow_attack(passlen); - return(ERROR(ERRSRV,ERRbadpw)); } { @@ -394,7 +390,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (smb_apasslen > MAX_PASSWORD_LENGTH) { overflow_attack(smb_apasslen); - return(ERROR(ERRSRV,ERRbadpw)); } memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); @@ -429,7 +424,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 > MAX_PASSWORD_LENGTH) { overflow_attack(passlen1); - return(ERROR(ERRSRV,ERRbadpw)); } passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); -- cgit From f5bd28c611cc76d640661bd51edbb454601ed474 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Sep 1997 18:43:02 +0000 Subject: Fixed potential security bug with receive_smb passing in a pointer to a pstring instead of a full sized buffer. Pointed out by : Matt Power mhpower@mit.edu Jeremy (jallison@whistle.com) --- source/smbd/password.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/source/smbd/password.c b/source/smbd/password.c index ed79d658a66..6d84a5ff61c 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1510,13 +1510,14 @@ BOOL check_hosts_equiv(char *user) int password_client = -1; static fstring pserver; +static char *secserver_inbuf = NULL; /**************************************************************************** attempted support for server level security ****************************************************************************/ BOOL server_cryptkey(char *buf) { - pstring inbuf,outbuf; + pstring outbuf; fstring pass_protocol; extern fstring remote_machine; char *p; @@ -1526,6 +1527,14 @@ BOOL server_cryptkey(char *buf) int port = SMB_PORT; BOOL ret; + if(secserver_inbuf == NULL) { + secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(secserver_inbuf == NULL) { + DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n")); + return False; + } + } + if (password_client >= 0) close(password_client); password_client = -1; @@ -1536,7 +1545,7 @@ BOOL server_cryptkey(char *buf) strcpy(pass_protocol,"NT LM 0.12"); } - bzero(inbuf,sizeof(inbuf)); + bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); bzero(outbuf,sizeof(outbuf)); for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { @@ -1602,8 +1611,8 @@ BOOL server_cryptkey(char *buf) send_smb(password_client,outbuf); - if (!receive_smb(password_client,inbuf,5000) || - CVAL(inbuf,0) != 0x82) { + if (!receive_smb(password_client,secserver_inbuf,5000) || + CVAL(secserver_inbuf,0) != 0x82) { DEBUG(1,("%s rejected the session\n",pserver)); close(password_client); password_client = -1; return(False); @@ -1624,21 +1633,21 @@ BOOL server_cryptkey(char *buf) SSVAL(outbuf,smb_flg2,0x1); send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) { + if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) { DEBUG(1,("%s rejected the protocol\n",pserver)); close(password_client); password_client= -1; return(False); } - if (!(CVAL(inbuf,smb_vwv1) & 1)) { + if (!(CVAL(secserver_inbuf,smb_vwv1) & 1)) { DEBUG(1,("%s isn't in user level security mode\n",pserver)); close(password_client); password_client= -1; return(False); } - memcpy(buf,inbuf,smb_len(inbuf)+4); + memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4); DEBUG(3,("password server OK\n")); @@ -1650,15 +1659,23 @@ attempted support for server level security ****************************************************************************/ BOOL server_validate(char *buf) { - pstring inbuf,outbuf; + pstring outbuf; BOOL ret; + if(secserver_inbuf == NULL) { + secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if(secserver_inbuf == NULL) { + DEBUG(0,("server_validate: malloc fail for input buffer.\n")); + return False; + } + } + if (password_client < 0) { DEBUG(1,("%s not connected\n",pserver)); return(False); } - bzero(inbuf,sizeof(inbuf)); + bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); memcpy(outbuf,buf,sizeof(outbuf)); /* send a session setup command */ @@ -1668,18 +1685,18 @@ BOOL server_validate(char *buf) set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); - SCVAL(inbuf,smb_rcls,1); + SCVAL(secserver_inbuf,smb_rcls,1); send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(inbuf,smb_rcls) != 0) { + if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) { DEBUG(1,("password server %s rejected the password\n",pserver)); return(False); } /* if logged in as guest then reject */ - if ((SVAL(inbuf,smb_vwv2) & 1) != 0) { + if ((SVAL(secserver_inbuf,smb_vwv2) & 1) != 0) { DEBUG(1,("password server %s gave us guest only\n",pserver)); return(False); } -- cgit From 82ab76981f47431e88a2aae4782fbebe6e5d8182 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Sep 1997 17:13:32 +0000 Subject: Syncing up Support providers. --- docs/textdocs/Support.txt | 56 ++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index 0a5c41b1950..d482ac39123 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -33,7 +33,7 @@ Region Number of entries ASIA 1 AUSTRALIA & NEW ZEALAND 18 CANADA 8 - EUROPE 34 + EUROPE 35 MIDDLE EAST 1 AFRICA @@ -1403,32 +1403,32 @@ http://www.alcove.fr Phone number: +33 01 40 85 80 06 ------------------------------------------------------------------------------ BERLIN - GERMANY -Name: innominate GbR -Address: Soldiner Str. 96, 13359 Berlin; Bundesland: Berlin; -Country: Germany -Phone: +49 30 49308195, +49 177 2649655 (mobil) -Fax: +49 30 49308196 -EMail: innominate@poboxes.com +Name: innominate + Multifunktionale Serverloesungen und IT-Dienstleistungen -Contact : Sascha Ottolski +Address: Stresemannstraße 128, 10117 Berlin +Country: Germany +Phone: +49 30 202 90 477 +Fax: +49 30 202 90 249 +EMail: info@innominate.de +Web: http://innominate.de Type of support: vor Ort, Email, Fernzugriff ueber Internet/ISDN, -Special -expertise: Wir verfuegen ueber umfangreiche Erfahrung mit Samba, vor allem - in Internet- und Intranetumgebungen. Neben Beratung, Dienstleistung - und Schulung bieten wir auch individuell vorkonfigurierte - Kommunikationsserver ("Lingo") auf der Basis von Linux an. - Neben anderen Modulen (ISDN/Internet/Intranet/Email/Proxy - u.a.) ist in Lingo ein Fileserver-Modul auf Samba-Basis inklusive - einem mehrstufigen Firewallsystem enthalten. - Außerdem verfuegt Lingo ueber eine grafische Administrations- - oberflaeche, mit der z.B. das Hinzufuegen von neuen Benutzern - von jedem Client per WWW-Browser moeglich ist. +Wir verfuegen ueber umfangreiche Erfahrung mit Samba, vor allem +in Intranetumgebungen. Neben Beratung, Dienstleistung +und Schulung bieten wir auch individuell vorkonfigurierte +Kommunikationsserver ("Lingo") auf der Basis von Linux an. +Neben anderen Modulen (ISDN/Internet/Intranet/Email/Proxy +u.a.) ist in Lingo ein Fileserver-Modul auf Samba-Basis inklusive +einem mehrstufigen Firewallsystem enthalten. +Außerdem verfuegt Lingo ueber eine grafische Administrations- +oberflaeche, mit der z.B. das Hinzufuegen von neuen Benutzern +von jedem Client per WWW-Browser moeglich ist. -Sample prices: - Komplettpreise fuer Lingo nach Vereinbarung - - 120 DM/Stunde fuer Dienstleistung - - Schulung nach Vereinbarung +Prices: Komplettpreise fuer Lingo nach Vereinbarung + 120 DM/Stunde fuer Dienstleistung + Schulung nach Vereinbarung ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ @@ -1547,6 +1547,18 @@ We are a Premium Partner of SCO and know and have used samba for four years. Our engineers know a lot about the installation of SCO Unix. ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +GREECE + +Yiorgos Adamopoulos +Electrical and Computer Engineer +email: adamo@InterWorks.org + +I can provide Samba support for the following operating systems throughout the +whole of Greece: Windows 3.11/95/NT, Ultrix, HP-UX, NetBSD, OpenBSD, SunOS, +Solaris, Linux, Irix. +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ SZEGED - HUNGARY -- cgit From 20bfde40b20f43cf8c6714ab9fb5a3fd17bc1575 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Oct 1997 05:19:24 +0000 Subject: This is all the NT error codes less than 1000. I extracted them using smbclient+netmon If we want to start supporting NT error codes in Samba (which may be forced upon us by buggy apps) then this is a good start. --- source/include/nterr.h | 505 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 source/include/nterr.h diff --git a/source/include/nterr.h b/source/include/nterr.h new file mode 100644 index 00000000000..92f02612dbc --- /dev/null +++ b/source/include/nterr.h @@ -0,0 +1,505 @@ +/* these are the NT error codes less than 1000. They are here for when + we start supporting NT error codes in Samba. They were extracted + using a loop in smbclient then printing a netmon sniff to a file */ + +#define NT_STATUS_UNSUCCESSFUL (1) +#define NT_STATUS_NOT_IMPLEMENTED (2) +#define NT_STATUS_INVALID_INFO_CLASS (3) +#define NT_STATUS_INFO_LENGTH_MISMATCH (4) +#define NT_STATUS_ACCESS_VIOLATION (5) +#define NT_STATUS_IN_PAGE_ERROR (6) +#define NT_STATUS_PAGEFILE_QUOTA (7) +#define NT_STATUS_INVALID_HANDLE (8) +#define NT_STATUS_BAD_INITIAL_STACK (9) +#define NT_STATUS_BAD_INITIAL_PC (10) +#define NT_STATUS_INVALID_CID (11) +#define NT_STATUS_TIMER_NOT_CANCELED (12) +#define NT_STATUS_INVALID_PARAMETER (13) +#define NT_STATUS_NO_SUCH_DEVICE (14) +#define NT_STATUS_NO_SUCH_FILE (15) +#define NT_STATUS_INVALID_DEVICE_REQUEST (16) +#define NT_STATUS_END_OF_FILE (17) +#define NT_STATUS_WRONG_VOLUME (18) +#define NT_STATUS_NO_MEDIA_IN_DEVICE (19) +#define NT_STATUS_UNRECOGNIZED_MEDIA (20) +#define NT_STATUS_NONEXISTENT_SECTOR (21) +#define NT_STATUS_MORE_PROCESSING_REQUIRED (22) +#define NT_STATUS_NO_MEMORY (23) +#define NT_STATUS_CONFLICTING_ADDRESSES (24) +#define NT_STATUS_NOT_MAPPED_VIEW (25) +#define NT_STATUS_UNABLE_TO_FREE_VM (26) +#define NT_STATUS_UNABLE_TO_DELETE_SECTION (27) +#define NT_STATUS_INVALID_SYSTEM_SERVICE (28) +#define NT_STATUS_ILLEGAL_INSTRUCTION (29) +#define NT_STATUS_INVALID_LOCK_SEQUENCE (30) +#define NT_STATUS_INVALID_VIEW_SIZE (31) +#define NT_STATUS_INVALID_FILE_FOR_SECTION (32) +#define NT_STATUS_ALREADY_COMMITTED (33) +#define NT_STATUS_ACCESS_DENIED (34) +#define NT_STATUS_BUFFER_TOO_SMALL (35) +#define NT_STATUS_OBJECT_TYPE_MISMATCH (36) +#define NT_STATUS_NONCONTINUABLE_EXCEPTION (37) +#define NT_STATUS_INVALID_DISPOSITION (38) +#define NT_STATUS_UNWIND (39) +#define NT_STATUS_BAD_STACK (40) +#define NT_STATUS_INVALID_UNWIND_TARGET (41) +#define NT_STATUS_NOT_LOCKED (42) +#define NT_STATUS_PARITY_ERROR (43) +#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (44) +#define NT_STATUS_NOT_COMMITTED (45) +#define NT_STATUS_INVALID_PORT_ATTRIBUTES (46) +#define NT_STATUS_PORT_MESSAGE_TOO_LONG (47) +#define NT_STATUS_INVALID_PARAMETER_MIX (48) +#define NT_STATUS_INVALID_QUOTA_LOWER (49) +#define NT_STATUS_DISK_CORRUPT_ERROR (50) +#define NT_STATUS_OBJECT_NAME_INVALID (51) +#define NT_STATUS_OBJECT_NAME_NOT_FOUND (52) +#define NT_STATUS_OBJECT_NAME_COLLISION (53) +#define NT_STATUS_HANDLE_NOT_WAITABLE (54) +#define NT_STATUS_PORT_DISCONNECTED (55) +#define NT_STATUS_DEVICE_ALREADY_ATTACHED (56) +#define NT_STATUS_OBJECT_PATH_INVALID (57) +#define NT_STATUS_OBJECT_PATH_NOT_FOUND (58) +#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (59) +#define NT_STATUS_DATA_OVERRUN (60) +#define NT_STATUS_DATA_LATE_ERROR (61) +#define NT_STATUS_DATA_ERROR (62) +#define NT_STATUS_CRC_ERROR (63) +#define NT_STATUS_SECTION_TOO_BIG (64) +#define NT_STATUS_PORT_CONNECTION_REFUSED (65) +#define NT_STATUS_INVALID_PORT_HANDLE (66) +#define NT_STATUS_SHARING_VIOLATION (67) +#define NT_STATUS_QUOTA_EXCEEDED (68) +#define NT_STATUS_INVALID_PAGE_PROTECTION (69) +#define NT_STATUS_MUTANT_NOT_OWNED (70) +#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (71) +#define NT_STATUS_PORT_ALREADY_SET (72) +#define NT_STATUS_SECTION_NOT_IMAGE (73) +#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (74) +#define NT_STATUS_THREAD_IS_TERMINATING (75) +#define NT_STATUS_BAD_WORKING_SET_LIMIT (76) +#define NT_STATUS_INCOMPATIBLE_FILE_MAP (77) +#define NT_STATUS_SECTION_PROTECTION (78) +#define NT_STATUS_EAS_NOT_SUPPORTED (79) +#define NT_STATUS_EA_TOO_LARGE (80) +#define NT_STATUS_NONEXISTENT_EA_ENTRY (81) +#define NT_STATUS_NO_EAS_ON_FILE (82) +#define NT_STATUS_EA_CORRUPT_ERROR (83) +#define NT_STATUS_FILE_LOCK_CONFLICT (84) +#define NT_STATUS_LOCK_NOT_GRANTED (85) +#define NT_STATUS_DELETE_PENDING (86) +#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (87) +#define NT_STATUS_UNKNOWN_REVISION (88) +#define NT_STATUS_REVISION_MISMATCH (89) +#define NT_STATUS_INVALID_OWNER (90) +#define NT_STATUS_INVALID_PRIMARY_GROUP (91) +#define NT_STATUS_NO_IMPERSONATION_TOKEN (92) +#define NT_STATUS_CANT_DISABLE_MANDATORY (93) +#define NT_STATUS_NO_LOGON_SERVERS (94) +#define NT_STATUS_NO_SUCH_LOGON_SESSION (95) +#define NT_STATUS_NO_SUCH_PRIVILEGE (96) +#define NT_STATUS_PRIVILEGE_NOT_HELD (97) +#define NT_STATUS_INVALID_ACCOUNT_NAME (98) +#define NT_STATUS_USER_EXISTS (99) +#define NT_STATUS_NO_SUCH_USER (100) +#define NT_STATUS_GROUP_EXISTS (101) +#define NT_STATUS_NO_SUCH_GROUP (102) +#define NT_STATUS_MEMBER_IN_GROUP (103) +#define NT_STATUS_MEMBER_NOT_IN_GROUP (104) +#define NT_STATUS_LAST_ADMIN (105) +#define NT_STATUS_WRONG_PASSWORD (106) +#define NT_STATUS_ILL_FORMED_PASSWORD (107) +#define NT_STATUS_PASSWORD_RESTRICTION (108) +#define NT_STATUS_LOGON_FAILURE (109) +#define NT_STATUS_ACCOUNT_RESTRICTION (110) +#define NT_STATUS_INVALID_LOGON_HOURS (111) +#define NT_STATUS_INVALID_WORKSTATION (112) +#define NT_STATUS_PASSWORD_EXPIRED (113) +#define NT_STATUS_ACCOUNT_DISABLED (114) +#define NT_STATUS_NONE_MAPPED (115) +#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (116) +#define NT_STATUS_LUIDS_EXHAUSTED (117) +#define NT_STATUS_INVALID_SUB_AUTHORITY (118) +#define NT_STATUS_INVALID_ACL (119) +#define NT_STATUS_INVALID_SID (120) +#define NT_STATUS_INVALID_SECURITY_DESCR (121) +#define NT_STATUS_PROCEDURE_NOT_FOUND (122) +#define NT_STATUS_INVALID_IMAGE_FORMAT (123) +#define NT_STATUS_NO_TOKEN (124) +#define NT_STATUS_BAD_INHERITANCE_ACL (125) +#define NT_STATUS_RANGE_NOT_LOCKED (126) +#define NT_STATUS_DISK_FULL (127) +#define NT_STATUS_SERVER_DISABLED (128) +#define NT_STATUS_SERVER_NOT_DISABLED (129) +#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (130) +#define NT_STATUS_GUIDS_EXHAUSTED (131) +#define NT_STATUS_INVALID_ID_AUTHORITY (132) +#define NT_STATUS_AGENTS_EXHAUSTED (133) +#define NT_STATUS_INVALID_VOLUME_LABEL (134) +#define NT_STATUS_SECTION_NOT_EXTENDED (135) +#define NT_STATUS_NOT_MAPPED_DATA (136) +#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (137) +#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (138) +#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (139) +#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (140) +#define NT_STATUS_FLOAT_DENORMAL_OPERAND (141) +#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (142) +#define NT_STATUS_FLOAT_INEXACT_RESULT (143) +#define NT_STATUS_FLOAT_INVALID_OPERATION (144) +#define NT_STATUS_FLOAT_OVERFLOW (145) +#define NT_STATUS_FLOAT_STACK_CHECK (146) +#define NT_STATUS_FLOAT_UNDERFLOW (147) +#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (148) +#define NT_STATUS_INTEGER_OVERFLOW (149) +#define NT_STATUS_PRIVILEGED_INSTRUCTION (150) +#define NT_STATUS_TOO_MANY_PAGING_FILES (151) +#define NT_STATUS_FILE_INVALID (152) +#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (153) +#define NT_STATUS_INSUFFICIENT_RESOURCES (154) +#define NT_STATUS_DFS_EXIT_PATH_FOUND (155) +#define NT_STATUS_DEVICE_DATA_ERROR (156) +#define NT_STATUS_DEVICE_NOT_CONNECTED (157) +#define NT_STATUS_DEVICE_POWER_FAILURE (158) +#define NT_STATUS_FREE_VM_NOT_AT_BASE (159) +#define NT_STATUS_MEMORY_NOT_ALLOCATED (160) +#define NT_STATUS_WORKING_SET_QUOTA (161) +#define NT_STATUS_MEDIA_WRITE_PROTECTED (162) +#define NT_STATUS_DEVICE_NOT_READY (163) +#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (164) +#define NT_STATUS_BAD_IMPERSONATION_LEVEL (165) +#define NT_STATUS_CANT_OPEN_ANONYMOUS (166) +#define NT_STATUS_BAD_VALIDATION_CLASS (167) +#define NT_STATUS_BAD_TOKEN_TYPE (168) +#define NT_STATUS_BAD_MASTER_BOOT_RECORD (169) +#define NT_STATUS_INSTRUCTION_MISALIGNMENT (170) +#define NT_STATUS_INSTANCE_NOT_AVAILABLE (171) +#define NT_STATUS_PIPE_NOT_AVAILABLE (172) +#define NT_STATUS_INVALID_PIPE_STATE (173) +#define NT_STATUS_PIPE_BUSY (174) +#define NT_STATUS_ILLEGAL_FUNCTION (175) +#define NT_STATUS_PIPE_DISCONNECTED (176) +#define NT_STATUS_PIPE_CLOSING (177) +#define NT_STATUS_PIPE_CONNECTED (178) +#define NT_STATUS_PIPE_LISTENING (179) +#define NT_STATUS_INVALID_READ_MODE (180) +#define NT_STATUS_IO_TIMEOUT (181) +#define NT_STATUS_FILE_FORCED_CLOSED (182) +#define NT_STATUS_PROFILING_NOT_STARTED (183) +#define NT_STATUS_PROFILING_NOT_STOPPED (184) +#define NT_STATUS_COULD_NOT_INTERPRET (185) +#define NT_STATUS_FILE_IS_A_DIRECTORY (186) +#define NT_STATUS_NOT_SUPPORTED (187) +#define NT_STATUS_REMOTE_NOT_LISTENING (188) +#define NT_STATUS_DUPLICATE_NAME (189) +#define NT_STATUS_BAD_NETWORK_PATH (190) +#define NT_STATUS_NETWORK_BUSY (191) +#define NT_STATUS_DEVICE_DOES_NOT_EXIST (192) +#define NT_STATUS_TOO_MANY_COMMANDS (193) +#define NT_STATUS_ADAPTER_HARDWARE_ERROR (194) +#define NT_STATUS_INVALID_NETWORK_RESPONSE (195) +#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (196) +#define NT_STATUS_BAD_REMOTE_ADAPTER (197) +#define NT_STATUS_PRINT_QUEUE_FULL (198) +#define NT_STATUS_NO_SPOOL_SPACE (199) +#define NT_STATUS_PRINT_CANCELLED (200) +#define NT_STATUS_NETWORK_NAME_DELETED (201) +#define NT_STATUS_NETWORK_ACCESS_DENIED (202) +#define NT_STATUS_BAD_DEVICE_TYPE (203) +#define NT_STATUS_BAD_NETWORK_NAME (204) +#define NT_STATUS_TOO_MANY_NAMES (205) +#define NT_STATUS_TOO_MANY_SESSIONS (206) +#define NT_STATUS_SHARING_PAUSED (207) +#define NT_STATUS_REQUEST_NOT_ACCEPTED (208) +#define NT_STATUS_REDIRECTOR_PAUSED (209) +#define NT_STATUS_NET_WRITE_FAULT (210) +#define NT_STATUS_PROFILING_AT_LIMIT (211) +#define NT_STATUS_NOT_SAME_DEVICE (212) +#define NT_STATUS_FILE_RENAMED (213) +#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (214) +#define NT_STATUS_NO_SECURITY_ON_OBJECT (215) +#define NT_STATUS_CANT_WAIT (216) +#define NT_STATUS_PIPE_EMPTY (217) +#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (218) +#define NT_STATUS_CANT_TERMINATE_SELF (219) +#define NT_STATUS_INVALID_SERVER_STATE (220) +#define NT_STATUS_INVALID_DOMAIN_STATE (221) +#define NT_STATUS_INVALID_DOMAIN_ROLE (222) +#define NT_STATUS_NO_SUCH_DOMAIN (223) +#define NT_STATUS_DOMAIN_EXISTS (224) +#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (225) +#define NT_STATUS_OPLOCK_NOT_GRANTED (226) +#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (227) +#define NT_STATUS_INTERNAL_DB_CORRUPTION (228) +#define NT_STATUS_INTERNAL_ERROR (229) +#define NT_STATUS_GENERIC_NOT_MAPPED (230) +#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (231) +#define NT_STATUS_INVALID_USER_BUFFER (232) +#define NT_STATUS_UNEXPECTED_IO_ERROR (233) +#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (234) +#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (235) +#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (236) +#define NT_STATUS_NOT_LOGON_PROCESS (237) +#define NT_STATUS_LOGON_SESSION_EXISTS (238) +#define NT_STATUS_INVALID_PARAMETER_1 (239) +#define NT_STATUS_INVALID_PARAMETER_2 (240) +#define NT_STATUS_INVALID_PARAMETER_3 (241) +#define NT_STATUS_INVALID_PARAMETER_4 (242) +#define NT_STATUS_INVALID_PARAMETER_5 (243) +#define NT_STATUS_INVALID_PARAMETER_6 (244) +#define NT_STATUS_INVALID_PARAMETER_7 (245) +#define NT_STATUS_INVALID_PARAMETER_8 (246) +#define NT_STATUS_INVALID_PARAMETER_9 (247) +#define NT_STATUS_INVALID_PARAMETER_10 (248) +#define NT_STATUS_INVALID_PARAMETER_11 (249) +#define NT_STATUS_INVALID_PARAMETER_12 (250) +#define NT_STATUS_REDIRECTOR_NOT_STARTED (251) +#define NT_STATUS_REDIRECTOR_STARTED (252) +#define NT_STATUS_STACK_OVERFLOW (253) +#define NT_STATUS_NO_SUCH_PACKAGE (254) +#define NT_STATUS_BAD_FUNCTION_TABLE (255) +#define NT_STATUS_DIRECTORY_NOT_EMPTY (257) +#define NT_STATUS_FILE_CORRUPT_ERROR (258) +#define NT_STATUS_NOT_A_DIRECTORY (259) +#define NT_STATUS_BAD_LOGON_SESSION_STATE (260) +#define NT_STATUS_LOGON_SESSION_COLLISION (261) +#define NT_STATUS_NAME_TOO_LONG (262) +#define NT_STATUS_FILES_OPEN (263) +#define NT_STATUS_CONNECTION_IN_USE (264) +#define NT_STATUS_MESSAGE_NOT_FOUND (265) +#define NT_STATUS_PROCESS_IS_TERMINATING (266) +#define NT_STATUS_INVALID_LOGON_TYPE (267) +#define NT_STATUS_NO_GUID_TRANSLATION (268) +#define NT_STATUS_CANNOT_IMPERSONATE (269) +#define NT_STATUS_IMAGE_ALREADY_LOADED (270) +#define NT_STATUS_ABIOS_NOT_PRESENT (271) +#define NT_STATUS_ABIOS_LID_NOT_EXIST (272) +#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (273) +#define NT_STATUS_ABIOS_NOT_LID_OWNER (274) +#define NT_STATUS_ABIOS_INVALID_COMMAND (275) +#define NT_STATUS_ABIOS_INVALID_LID (276) +#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (277) +#define NT_STATUS_ABIOS_INVALID_SELECTOR (278) +#define NT_STATUS_NO_LDT (279) +#define NT_STATUS_INVALID_LDT_SIZE (280) +#define NT_STATUS_INVALID_LDT_OFFSET (281) +#define NT_STATUS_INVALID_LDT_DESCRIPTOR (282) +#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (283) +#define NT_STATUS_RXACT_INVALID_STATE (284) +#define NT_STATUS_RXACT_COMMIT_FAILURE (285) +#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (286) +#define NT_STATUS_TOO_MANY_OPENED_FILES (287) +#define NT_STATUS_CANCELLED (288) +#define NT_STATUS_CANNOT_DELETE (289) +#define NT_STATUS_INVALID_COMPUTER_NAME (290) +#define NT_STATUS_FILE_DELETED (291) +#define NT_STATUS_SPECIAL_ACCOUNT (292) +#define NT_STATUS_SPECIAL_GROUP (293) +#define NT_STATUS_SPECIAL_USER (294) +#define NT_STATUS_MEMBERS_PRIMARY_GROUP (295) +#define NT_STATUS_FILE_CLOSED (296) +#define NT_STATUS_TOO_MANY_THREADS (297) +#define NT_STATUS_THREAD_NOT_IN_PROCESS (298) +#define NT_STATUS_TOKEN_ALREADY_IN_USE (299) +#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (300) +#define NT_STATUS_COMMITMENT_LIMIT (301) +#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (302) +#define NT_STATUS_INVALID_IMAGE_NOT_MZ (303) +#define NT_STATUS_INVALID_IMAGE_PROTECT (304) +#define NT_STATUS_INVALID_IMAGE_WIN_16 (305) +#define NT_STATUS_LOGON_SERVER_CONFLICT (306) +#define NT_STATUS_TIME_DIFFERENCE_AT_DC (307) +#define NT_STATUS_SYNCHRONIZATION_REQUIRED (308) +#define NT_STATUS_DLL_NOT_FOUND (309) +#define NT_STATUS_OPEN_FAILED (310) +#define NT_STATUS_IO_PRIVILEGE_FAILED (311) +#define NT_STATUS_ORDINAL_NOT_FOUND (312) +#define NT_STATUS_ENTRYPOINT_NOT_FOUND (313) +#define NT_STATUS_CONTROL_C_EXIT (314) +#define NT_STATUS_LOCAL_DISCONNECT (315) +#define NT_STATUS_REMOTE_DISCONNECT (316) +#define NT_STATUS_REMOTE_RESOURCES (317) +#define NT_STATUS_LINK_FAILED (318) +#define NT_STATUS_LINK_TIMEOUT (319) +#define NT_STATUS_INVALID_CONNECTION (320) +#define NT_STATUS_INVALID_ADDRESS (321) +#define NT_STATUS_DLL_INIT_FAILED (322) +#define NT_STATUS_MISSING_SYSTEMFILE (323) +#define NT_STATUS_UNHANDLED_EXCEPTION (324) +#define NT_STATUS_APP_INIT_FAILURE (325) +#define NT_STATUS_PAGEFILE_CREATE_FAILED (326) +#define NT_STATUS_NO_PAGEFILE (327) +#define NT_STATUS_INVALID_LEVEL (328) +#define NT_STATUS_WRONG_PASSWORD_CORE (329) +#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (330) +#define NT_STATUS_PIPE_BROKEN (331) +#define NT_STATUS_REGISTRY_CORRUPT (332) +#define NT_STATUS_REGISTRY_IO_FAILED (333) +#define NT_STATUS_NO_EVENT_PAIR (334) +#define NT_STATUS_UNRECOGNIZED_VOLUME (335) +#define NT_STATUS_SERIAL_NO_DEVICE_INITED (336) +#define NT_STATUS_NO_SUCH_ALIAS (337) +#define NT_STATUS_MEMBER_NOT_IN_ALIAS (338) +#define NT_STATUS_MEMBER_IN_ALIAS (339) +#define NT_STATUS_ALIAS_EXISTS (340) +#define NT_STATUS_LOGON_NOT_GRANTED (341) +#define NT_STATUS_TOO_MANY_SECRETS (342) +#define NT_STATUS_SECRET_TOO_LONG (343) +#define NT_STATUS_INTERNAL_DB_ERROR (344) +#define NT_STATUS_FULLSCREEN_MODE (345) +#define NT_STATUS_TOO_MANY_CONTEXT_IDS (346) +#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (347) +#define NT_STATUS_NOT_REGISTRY_FILE (348) +#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (349) +#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (350) +#define NT_STATUS_FT_MISSING_MEMBER (351) +#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (352) +#define NT_STATUS_ILLEGAL_CHARACTER (353) +#define NT_STATUS_UNMAPPABLE_CHARACTER (354) +#define NT_STATUS_UNDEFINED_CHARACTER (355) +#define NT_STATUS_FLOPPY_VOLUME (356) +#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (357) +#define NT_STATUS_FLOPPY_WRONG_CYLINDER (358) +#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (359) +#define NT_STATUS_FLOPPY_BAD_REGISTERS (360) +#define NT_STATUS_DISK_RECALIBRATE_FAILED (361) +#define NT_STATUS_DISK_OPERATION_FAILED (362) +#define NT_STATUS_DISK_RESET_FAILED (363) +#define NT_STATUS_SHARED_IRQ_BUSY (364) +#define NT_STATUS_FT_ORPHANING (365) +#define NT_STATUS_PARTITION_FAILURE (370) +#define NT_STATUS_INVALID_BLOCK_LENGTH (371) +#define NT_STATUS_DEVICE_NOT_PARTITIONED (372) +#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (373) +#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (374) +#define NT_STATUS_EOM_OVERFLOW (375) +#define NT_STATUS_NO_MEDIA (376) +#define NT_STATUS_NO_SUCH_MEMBER (378) +#define NT_STATUS_INVALID_MEMBER (379) +#define NT_STATUS_KEY_DELETED (380) +#define NT_STATUS_NO_LOG_SPACE (381) +#define NT_STATUS_TOO_MANY_SIDS (382) +#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (383) +#define NT_STATUS_KEY_HAS_CHILDREN (384) +#define NT_STATUS_CHILD_MUST_BE_VOLATILE (385) +#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (386) +#define NT_STATUS_DRIVER_INTERNAL_ERROR (387) +#define NT_STATUS_INVALID_DEVICE_STATE (388) +#define NT_STATUS_IO_DEVICE_ERROR (389) +#define NT_STATUS_DEVICE_PROTOCOL_ERROR (390) +#define NT_STATUS_BACKUP_CONTROLLER (391) +#define NT_STATUS_LOG_FILE_FULL (392) +#define NT_STATUS_TOO_LATE (393) +#define NT_STATUS_NO_TRUST_LSA_SECRET (394) +#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (395) +#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (396) +#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (397) +#define NT_STATUS_EVENTLOG_FILE_CORRUPT (398) +#define NT_STATUS_EVENTLOG_CANT_START (399) +#define NT_STATUS_TRUST_FAILURE (400) +#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (401) +#define NT_STATUS_NETLOGON_NOT_STARTED (402) +#define NT_STATUS_ACCOUNT_EXPIRED (403) +#define NT_STATUS_POSSIBLE_DEADLOCK (404) +#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (405) +#define NT_STATUS_REMOTE_SESSION_LIMIT (406) +#define NT_STATUS_EVENTLOG_FILE_CHANGED (407) +#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (408) +#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (409) +#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (410) +#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (411) +#define NT_STATUS_FS_DRIVER_REQUIRED (412) +#define NT_STATUS_NO_USER_SESSION_KEY (514) +#define NT_STATUS_USER_SESSION_DELETED (515) +#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (516) +#define NT_STATUS_INSUFF_SERVER_RESOURCES (517) +#define NT_STATUS_INVALID_BUFFER_SIZE (518) +#define NT_STATUS_INVALID_ADDRESS_COMPONENT (519) +#define NT_STATUS_INVALID_ADDRESS_WILDCARD (520) +#define NT_STATUS_TOO_MANY_ADDRESSES (521) +#define NT_STATUS_ADDRESS_ALREADY_EXISTS (522) +#define NT_STATUS_ADDRESS_CLOSED (523) +#define NT_STATUS_CONNECTION_DISCONNECTED (524) +#define NT_STATUS_CONNECTION_RESET (525) +#define NT_STATUS_TOO_MANY_NODES (526) +#define NT_STATUS_TRANSACTION_ABORTED (527) +#define NT_STATUS_TRANSACTION_TIMED_OUT (528) +#define NT_STATUS_TRANSACTION_NO_RELEASE (529) +#define NT_STATUS_TRANSACTION_NO_MATCH (530) +#define NT_STATUS_TRANSACTION_RESPONDED (531) +#define NT_STATUS_TRANSACTION_INVALID_ID (532) +#define NT_STATUS_TRANSACTION_INVALID_TYPE (533) +#define NT_STATUS_NOT_SERVER_SESSION (534) +#define NT_STATUS_NOT_CLIENT_SESSION (535) +#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (536) +#define NT_STATUS_DEBUG_ATTACH_FAILED (537) +#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (538) +#define NT_STATUS_DATA_NOT_ACCEPTED (539) +#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (540) +#define NT_STATUS_VDM_HARD_ERROR (541) +#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (542) +#define NT_STATUS_REPLY_MESSAGE_MISMATCH (543) +#define NT_STATUS_MAPPED_ALIGNMENT (544) +#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (545) +#define NT_STATUS_LOST_WRITEBEHIND_DATA (546) +#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (547) +#define NT_STATUS_PASSWORD_MUST_CHANGE (548) +#define NT_STATUS_NOT_FOUND (549) +#define NT_STATUS_NOT_TINY_STREAM (550) +#define NT_STATUS_RECOVERY_FAILURE (551) +#define NT_STATUS_STACK_OVERFLOW_READ (552) +#define NT_STATUS_FAIL_CHECK (553) +#define NT_STATUS_DUPLICATE_OBJECTID (554) +#define NT_STATUS_OBJECTID_EXISTS (555) +#define NT_STATUS_CONVERT_TO_LARGE (556) +#define NT_STATUS_RETRY (557) +#define NT_STATUS_FOUND_OUT_OF_SCOPE (558) +#define NT_STATUS_ALLOCATE_BUCKET (559) +#define NT_STATUS_PROPSET_NOT_FOUND (560) +#define NT_STATUS_MARSHALL_OVERFLOW (561) +#define NT_STATUS_INVALID_VARIANT (562) +#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (563) +#define NT_STATUS_ACCOUNT_LOCKED_OUT (564) +#define NT_STATUS_HANDLE_NOT_CLOSABLE (565) +#define NT_STATUS_CONNECTION_REFUSED (566) +#define NT_STATUS_GRACEFUL_DISCONNECT (567) +#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (568) +#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (569) +#define NT_STATUS_CONNECTION_INVALID (570) +#define NT_STATUS_CONNECTION_ACTIVE (571) +#define NT_STATUS_NETWORK_UNREACHABLE (572) +#define NT_STATUS_HOST_UNREACHABLE (573) +#define NT_STATUS_PROTOCOL_UNREACHABLE (574) +#define NT_STATUS_PORT_UNREACHABLE (575) +#define NT_STATUS_REQUEST_ABORTED (576) +#define NT_STATUS_CONNECTION_ABORTED (577) +#define NT_STATUS_BAD_COMPRESSION_BUFFER (578) +#define NT_STATUS_USER_MAPPED_FILE (579) +#define NT_STATUS_AUDIT_FAILED (580) +#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (581) +#define NT_STATUS_CONNECTION_COUNT_LIMIT (582) +#define NT_STATUS_LOGIN_TIME_RESTRICTION (583) +#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (584) +#define NT_STATUS_IMAGE_MP_UP_MISMATCH (585) +#define NT_STATUS_INSUFFICIENT_LOGON_INFO (592) +#define NT_STATUS_BAD_DLL_ENTRYPOINT (593) +#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (594) +#define NT_STATUS_LPC_REPLY_LOST (595) +#define NT_STATUS_IP_ADDRESS_CONFLICT1 (596) +#define NT_STATUS_IP_ADDRESS_CONFLICT2 (597) +#define NT_STATUS_REGISTRY_QUOTA_LIMIT (598) +#define NT_STATUS_PATH_NOT_COVERED (599) +#define NT_STATUS_NO_CALLBACK_ACTIVE (600) +#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (601) +#define NT_STATUS_PWD_TOO_SHORT (602) +#define NT_STATUS_PWD_TOO_RECENT (603) +#define NT_STATUS_PWD_HISTORY_CONFLICT (604) +#define NT_STATUS_PLUGPLAY_NO_DEVICE (606) +#define NT_STATUS_UNSUPPORTED_COMPRESSION (607) +#define NT_STATUS_INVALID_HW_PROFILE (608) +#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (609) +#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (610) +#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (611) +#define NT_STATUS_RESOURCE_NOT_OWNED (612) +#define NT_STATUS_TOO_MANY_LINKS (613) +#define NT_STATUS_QUOTA_LIST_INCONSISTENT (614) +#define NT_STATUS_FILE_IS_OFFLINE (615) -- cgit From 0eb9a590430c328e6ebc46ff8ab05f181921769a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Oct 1997 05:21:14 +0000 Subject: a little hack to smbclient to support extracting NT error codes --- source/client/client.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/client/client.c b/source/client/client.c index 275d03ddba2..403eea2fc99 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -275,6 +275,18 @@ static BOOL chkpath(char *path,BOOL report) *p++ = 4; strcpy(p,path2); +#if 0 + { + /* this little bit of code can be used to extract NT error codes. + Just feed a bunch of "cd foo" commands to smbclient then watch + in netmon (tridge) */ + static int code=0; + SIVAL(outbuf, smb_rcls, code | 0xC0000000); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14)); + code++; + } +#endif + send_smb(Client,outbuf); receive_smb(Client,inbuf,CLIENT_TIMEOUT); -- cgit From d40199f4fe1344058267859820cb36b77a20442a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Oct 1997 05:21:47 +0000 Subject: a bit of bounds checking --- source/client/clientutil.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/client/clientutil.c b/source/client/clientutil.c index d16e5a471fc..ed5497782b3 100644 --- a/source/client/clientutil.c +++ b/source/client/clientutil.c @@ -126,6 +126,13 @@ BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, { this_data = SVAL(inbuf,smb_drcnt); this_param = SVAL(inbuf,smb_prcnt); + + if (this_data + *data_len > total_data || + this_param + *param_len > total_param) { + DEBUG(1,("Data overflow in cli_receive_trans_response\n")); + return False; + } + if (this_data) memcpy(*data + SVAL(inbuf,smb_drdisp), smb_base(inbuf) + SVAL(inbuf,smb_droff), @@ -453,6 +460,11 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu /* send a session setup command */ bzero(outbuf,smb_size); + if (passlen > MAX_PASSWORD_LENGTH) { + DEBUG(1,("password too long %d\n", passlen)); + return False; + } + if (Protocol < PROTOCOL_NT1) { set_message(outbuf,10,1 + strlen(username) + passlen,True); CVAL(outbuf,smb_com) = SMBsesssetupX; -- cgit From 25b7ada3587d1fe68164a2339d7f0fbcecf18e53 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Oct 1997 05:24:02 +0000 Subject: fix some "shadows global" errors. --- source/smbd/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/smbd/server.c b/source/smbd/server.c index b250572a1f4..826b17121fd 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -2441,7 +2441,7 @@ static void process_smb(char *inbuf, char *outbuf) static BOOL open_oplock_ipc() { struct sockaddr_in sock_name; - int name_len = sizeof(sock_name); + int len = sizeof(sock_name); DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); @@ -2456,7 +2456,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); } /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0) + if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) { DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", strerror(errno))); @@ -2473,7 +2473,7 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); /**************************************************************************** process an oplock break message. ****************************************************************************/ -static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) +static BOOL process_local_message(int sock, char *buffer, int buf_size) { int32 msg_len; int16 from_port; @@ -2543,7 +2543,7 @@ oplocks. Returning success.\n")); toaddr.sin_port = htons(from_port); toaddr.sin_family = AF_INET; - if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, + if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", -- cgit From 297d5ef46ccba99596610c4c6a09399af665f2cf Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 4 Oct 1997 16:10:21 +0000 Subject: packet parsing routines. for use in SMB and Mailslots --- source/smbparse.c | 385 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 source/smbparse.c diff --git a/source/smbparse.c b/source/smbparse.c new file mode 100644 index 00000000000..bff1a1453a4 --- /dev/null +++ b/source/smbparse.c @@ -0,0 +1,385 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba utility functions + Copyright (C) Luke Leighton 1996 - 1997 + + 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 DEBUGLEVEL; + + +/******************************************************************* +reads or writes an NTTIME structure. +********************************************************************/ +char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align) +{ + if (nttime == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, nttime->low , 0); q += 4; /* low part */ + RW_IVAL(io, q, nttime->high, 0); q += 4; /* high part */ + + return q; +} + +/******************************************************************* +reads or writes a DOM_SID structure. +********************************************************************/ +char* smb_io_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) +{ + int i; + + if (sid == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_CVAL(io, q, sid->sid_no, 0); q++; + RW_CVAL(io, q, sid->num_auths, 0); q++; + + for (i = 0; i < 6; i++) + { + RW_CVAL(io, q, sid->id_auth[i], 0); q++; + } + + /* oops! XXXX should really issue a warning here... */ + if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; + + RW_PSVAL(io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; + + return q; +} + +/******************************************************************* +reads or writes a UNIHDR structure. +********************************************************************/ +char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align) +{ + if (hdr == NULL) return NULL; + + /* should be value 4, so enforce it. */ + hdr->undoc = 4; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, hdr->uni_max_len, 0); q += 4; + RW_IVAL(io, q, hdr->uni_str_len, 0); q += 4; + RW_IVAL(io, q, hdr->undoc , 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a UNIHDR2 structure. +********************************************************************/ +char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align) +{ + if (hdr2 == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_unihdr(io, &(hdr2->unihdr), q, base, align); + RW_IVAL(io, q, hdr2->undoc_buffer, 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a UNISTR structure. +XXXX NOTE: UNISTR structures NEED to be null-terminated. +********************************************************************/ +char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align) +{ + if (uni == NULL) return NULL; + + q = align_offset(q, base, align); + + if (io) + { + /* io True indicates read _from_ the SMB buffer into the string */ + q += 2 * unistrcpy((char*)uni->buffer, q); + } + else + { + /* io True indicates copy _from_ the string into SMB buffer */ + q += 2 * unistrcpy(q, (char*)uni->buffer); + } + return q; +} + +/******************************************************************* +reads or writes a UNISTR2 structure. +XXXX NOTE: UNISTR2 structures need NOT be null-terminated. + the uni_str_len member tells you how long the string is; + the uni_max_len member tells you how large the buffer is. +********************************************************************/ +char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align) +{ + if (uni2 == NULL) return NULL; + + q = align_offset(q, base, align); + + /* should be value 0, so enforce it. */ + uni2->undoc = 0; + + RW_IVAL(io, q, uni2->uni_max_len, 0); q += 4; + RW_IVAL(io, q, uni2->undoc , 0); q += 4; + RW_IVAL(io, q, uni2->uni_str_len, 0); q += 4; + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN; + if (uni2->uni_str_len > MAX_UNISTRLEN) uni2->uni_str_len = MAX_UNISTRLEN; + + /* buffer advanced by indicated length of string + NOT by searching for null-termination */ + RW_PSVAL(io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; + + return q; +} + +/******************************************************************* +reads or writes a DOM_SID2 structure. +********************************************************************/ +char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align) +{ + if (sid2 == NULL) return NULL; + + q = align_offset(q, base, align); + + /* should be value 5, so enforce it */ + sid2->type = 5; + + /* should be value 0, so enforce it */ + sid2->undoc = 0; + + RW_IVAL(io, q, sid2->type , 0); q += 4; + RW_IVAL(io, q, sid2->undoc, 0); q += 4; + + q = smb_io_unihdr2(io, &(sid2->hdr), q, base, align); + q = smb_io_unistr (io, &(sid2->str), q, base, align); + + return q; +} + +/******************************************************************* +reads or writes a DOM_RID2 structure. +********************************************************************/ +char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align) +{ + if (rid2 == NULL) return NULL; + + q = align_offset(q, base, align); + + /* should be value 5, so enforce it */ + rid2->type = 5; + + /* should be value 5, so enforce it */ + rid2->undoc = 5; + + RW_IVAL(io, q, rid2->type, 0); q += 4; + RW_IVAL(io, q, rid2->undoc , 0); q += 4; + RW_IVAL(io, q, rid2->rid , 0); q += 4; + RW_IVAL(io, q, rid2->rid_idx , 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a DOM_LOG_INFO structure. +********************************************************************/ +char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align) +{ + if (log == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, log->undoc_buffer, 0); q += 4; + + q = smb_io_unistr2(io, &(log->uni_logon_srv), q, base, align); + q = smb_io_unistr2(io, &(log->uni_acct_name), q, base, align); + + RW_SVAL(io, q, log->sec_chan, 0); q += 2; + + /* XXXX no alignment required between sec_chan and uni_comp_name */ + q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, 0); + + return q; +} + +/******************************************************************* +reads or writes a DOM_CRED structure. +********************************************************************/ +char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align) +{ + if (cred == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_PCVAL(io, q, cred->data, 8); q += 8; + RW_IVAL (io, q, cred->timestamp, 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a DOM_CLNT_INFO structure. +********************************************************************/ +char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align) +{ + if (clnt == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_log_info(io, &(clnt->login), q, base, align); + q = smb_io_cred (io, &(clnt->cred ), q, base, align); + + return q; +} + +/******************************************************************* +reads or writes a DOM_LOGON_ID structure. +********************************************************************/ +char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align) +{ + if (log == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, log->low , 0); q += 4; + RW_IVAL(io, q, log->high, 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes an RC4_OWF structure. +********************************************************************/ +char* smb_io_rc4_owf(BOOL io, RC4_OWF *hash, char *q, char *base, int align) +{ + if (hash == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_PCVAL(io, q, hash->data, 16); q += 16; + + return q; +} + +/******************************************************************* +reads or writes an DOM_ID_INFO_1 structure. +********************************************************************/ +char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align) +{ + if (id == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align); + + RW_IVAL(io, q, id->param, 0); q += 4; + q = smb_io_logon_id(io, &(id->logon_id), q, base, align); + + q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align); + q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align); + + q = smb_io_rc4_owf(io, &(id->rc4_lm_owf), q, base, align); + q = smb_io_rc4_owf(io, &(id->rc4_nt_owf), q, base, align); + + q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align); + q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align); + q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align); + + return q; +} + +/******************************************************************* +reads or writes a DOM_SAM_INFO structure. +********************************************************************/ +char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align) +{ + if (sam == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_clnt_info(io, &(sam->client ), q, base, align); + q = smb_io_cred (io, &(sam->rtn_cred), q, base, align); + + RW_IVAL(io, q, sam->logon_level, 0); q += 4; + RW_SVAL(io, q, sam->auth_level , 0); q += 4; + + switch (sam->auth_level) + { + case 1: + { + q = smb_io_id_info1(io, &(sam->auth.id1), q, base, align); + break; + } + default: + { + /* PANIC! */ + break; + } + } + return q; +} + +/******************************************************************* +reads or writes a DOM_GID structure. +********************************************************************/ +char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align) +{ + if (gid == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, gid->gid , 0); q += 4; + RW_IVAL(io, q, gid->attr, 0); q += 4; + + return q; +} + +#if 0 +/******************************************************************* +reads or writes a structure. +********************************************************************/ + char* smb_io_(BOOL io, *, char *q, char *base, int align) +{ + if (== NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, , 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + char* smb_io_(BOOL io, *, char *q, char *base, int align) +{ + if (== NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, , 0); q += 4; + + return q; +} +#endif -- cgit From 4b3f9b281b3b1c1064992d19fef1d782dc6f1ff1 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 4 Oct 1997 16:26:02 +0000 Subject: added structures readable and writeable by smbparse.c routines into and out of SMB or Mailslot packets. --- source/include/smb.h | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/source/include/smb.h b/source/include/smb.h index 66da2099c77..37474436cac 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -252,6 +252,188 @@ typedef char fstring[128]; typedef fstring string; +/* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ +typedef uint32 UTIME; + +/* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ +typedef struct nttime +{ + uint32 low; + uint32 high; + +} NTTIME; + + +#define MAXSUBAUTHS 10 /* max sub authorities in a SID */ + +/* DOM_SID - security id */ +typedef struct sid_info +{ + uint8 sid_no; /* SID revision number */ + uint8 num_auths; /* number of sub-authorities */ + uint8 id_auth[6]; /* Identifier Authority */ + uint16 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ + +} DOM_SID; + +/* UNIHDR - unicode string header */ +typedef struct unihdr_info +{ + uint16 uni_max_len; + uint16 uni_str_len; + uint32 undoc; /* usually has a value of 4 */ + +} UNIHDR; + +/* UNIHDR2 - unicode string header and undocumented buffer */ +typedef struct unihdr2_info +{ + UNIHDR unihdr; + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + +} UNIHDR2; + +/* clueless as to what maximum length should be */ +#define MAX_UNISTRLEN 1024 + +/* UNISTR - unicode string size and buffer */ +typedef struct unistr_info +{ + uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */ + +} UNISTR; + +/* UNISTR2 - unicode string size and buffer */ +typedef struct unistr2_info +{ + uint32 uni_max_len; + uint32 undoc; + uint32 uni_str_len; + uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */ + +} UNISTR2; + +/* DOM_SID2 - domain SID structure - SIDs stored in unicode */ +typedef struct domsid2_info +{ + uint32 type; /* value is 5 */ + uint32 undoc; /* value is 0 */ + UNIHDR2 hdr; /* XXXX conflict between hdr and str for length */ + UNISTR str; /* XXXX conflict between hdr and str for length */ + +} DOM_SID2; + +/* DOM_RID2 - domain RID structure */ +typedef struct domrid2_info +{ + uint32 type; /* value is 5 */ + uint32 undoc; /* value is 5 */ + uint32 rid; + uint32 rid_idx; /* don't know what this is */ + +} DOM_RID2; + +/* DOM_LOG_INFO - login info */ +typedef struct log_info +{ + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + UNISTR2 uni_acct_name; /* account name */ + uint16 sec_chan; /* secure channel type */ + UNISTR2 uni_comp_name; /* client machine name */ + +} DOM_LOG_INFO; + +/* DOM_CREDs - client or server credentials */ +typedef struct cred_info +{ + uint8 data[8]; /* credentials */ + UTIME timestamp; /* credential time-stamp */ + +} DOM_CRED; + +/* DOM_CLNT_INFO - client info */ +typedef struct clnt_info +{ + DOM_LOG_INFO login; + DOM_CRED cred; + +} DOM_CLNT_INFO; + +/* DOM_LOGON_ID - logon id */ +typedef struct logon_info +{ + uint32 low; + uint32 high; + +} DOM_LOGON_ID; + +/* RC4_OWF */ +typedef struct rc4_owf_info +{ + uint8 data[16]; + +} RC4_OWF; + + +/* DOM_ID_INFO_1 */ +typedef struct id_info_1 +{ + UNIHDR hdr_domain_name; /* domain name unicode header */ + uint32 param; /* param control */ + DOM_LOGON_ID logon_id; /* logon ID */ + UNIHDR hdr_user_name; /* user name unicode header */ + UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ + RC4_OWF rc4_lm_owf; /* rc4 LM OWF Password */ + RC4_OWF rc4_nt_owf; /* rc4 NT OWF Password */ + UNISTR2 uni_domain_name; /* domain name unicode string */ + UNISTR2 uni_user_name; /* user name unicode string */ + UNISTR2 uni_workgroup_name; /* workgroup name unicode string */ + +} DOM_ID_INFO_1; + +/* SAM_INFO - sam logon/off id structure */ +typedef struct sam_info +{ + DOM_CLNT_INFO client; + DOM_CRED rtn_cred; /* return credentials */ + uint16 logon_level; + uint32 auth_level; /* undocumented */ + + union + { + DOM_ID_INFO_1 id1; /* auth-level 1 */ + + } auth; + +} DOM_SAM_INFO; + +/* DOM_GID - group id + user attributes */ +typedef struct gid_info +{ + uint32 gid; /* group id */ + uint32 attr; + +} DOM_GID; + +/* RPC_HEADER - ms rpc header */ +typedef struct rpc_hdr_info +{ + uint8 major; /* 5 - RPC major version */ + uint8 minor; /* 0 - RPC minor version */ + uint8 pkt_type; /* 2 - RPC response packet */ + uint8 frag; /* 3 - first frag + last frag */ + uint32 pack_type; /* 0x0000 0010 - packed data representation */ + uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */ + uint16 auth_len; /* 0 - authentication length */ + uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */ + uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ + uint16 context_id; /* 0 - presentation context identifier */ + uint8 cancel_count; /* 0 - cancel count */ + uint8 reserved; /* 0 - reserved */ +} RPC_HEADER; + + struct smb_passwd { int smb_userid; char *smb_name; -- cgit From b0ffd75acfd3660512cccecdf50a183c3abccfcb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 4 Oct 1997 16:42:09 +0000 Subject: added some RW_XXXX wrapper macros with an extra i/o argument, to call XXXX or SXXXX as appropriate. added some for-loop pointer macros that will do a batch of data into a (fixed length) buffer. no length validation is done in the macro itself. note: there are some CAREFUL_ALIGNMENT macros missing. i think. --- source/include/byteorder.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index a55789a4036..4991338f263 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -88,6 +88,28 @@ it also defines lots of intermediate macros, just ignore those :-) */ +/* some switch macros that do both store and read to and from SMB buffers */ + +#define RW_PCVAL(read,inbuf,outbuf,len) \ + if (read) { PCVAL (inbuf,0,outbuf,len) } \ + else { PSCVAL(inbuf,0,outbuf,len) } + +#define RW_PSVAL(read,inbuf,outbuf,len) \ + if (read) { PSVAL (inbuf,0,outbuf,len) } \ + else { PSSVAL(inbuf,0,outbuf,len) } + +#define RW_CVAL(read, inbuf, outbuf, offset) \ + if (read) (outbuf) = CVAL (inbuf,offset); \ + else SCVAL(inbuf,offset,outbuf); + +#define RW_IVAL(read, inbuf, outbuf, offset) \ + if (read) (outbuf)= IVAL (inbuf,offset); \ + else SIVAL(inbuf,offset,outbuf); + +#define RW_SVAL(read, inbuf, outbuf, offset) \ + if (read) (outbuf)= SVAL (inbuf,offset); \ + else SSVAL(inbuf,offset,outbuf); + #undef CAREFUL_ALIGNMENT /* we know that the 386 can handle misalignment and has the "right" @@ -123,14 +145,41 @@ it also defines lots of intermediate macros, just ignore those :-) WARNING: This section is dependent on the length of int16 and int32 being correct */ + +/* get single value from an SMB buffer */ #define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) #define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) #define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos))) #define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos))) + +/* store single value in an SMB buffer */ #define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val)) #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val)) #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) + +#define SMBMACRO(macro,buf,pos,val,len,size) \ +{ int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); } + +#define SSMBMACRO(macro,buf,pos,val,len,size) \ +{ int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); } + +/* reads multiple data from an SMB buffer */ +#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1) +#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2) +#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4) +#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1) +#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2) +#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4) + +/* stores multiple data in an SMB buffer */ +#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1) +#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2) +#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4) +#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1) +#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2) +#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4) + #endif -- cgit From b0ad811cda3dcffed5b24104229813cdb17b014f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 4 Oct 1997 16:51:43 +0000 Subject: proto.h: - recreated, as usual. smb.h: - added RPC_HDR structure - the 18 byte MSRPC header smbparse.c: - added smb_io_rpc_hdr() function to read/write the RPC_HDR structure. util.c: - added align2, align4, align_offset functions. - added skip_unicode_string, unistrcpy, unistrncpy functions. - modified unistrcpy and unistrncpy to return the number of unicode characters returned, effectively making skip_unicode_string redundant. --- source/include/proto.h | 11 ++++- source/include/smb.h | 8 +++- source/lib/util.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ source/smbparse.c | 27 ++++++++---- 4 files changed, 148 insertions(+), 11 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 8818b9b5274..4ec4a42f2aa 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -565,7 +565,9 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, /*The following definitions come from params.c */ -BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)); +BOOL pm_process( char *FileName, + BOOL (*sfunc)(char *), + BOOL (*pfunc)(char *, char *) ); /*The following definitions come from password.c */ @@ -986,5 +988,12 @@ void file_unlock(int fd); BOOL is_myname(char *s); void set_remote_arch(enum remote_arch_types type); enum remote_arch_types get_remote_arch(); +char *skip_unicode_string(char *buf,int n); +char *unistr(char *buf); +int unistrncpy(char *dst, char *src, int len); +int unistrcpy(char *dst, char *src); void fstrcpy(char *dest, char *src); void pstrcpy(char *dest, char *src); +char *align4(char *q, char *base); +char *align2(char *q, char *base); +char *align_offset(char *q, char *base, int align_offset); diff --git a/source/include/smb.h b/source/include/smb.h index 37474436cac..b999c136677 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -80,6 +80,10 @@ typedef short int16; typedef int int32; #endif +#ifndef uint8 +typedef unsigned char uint8; +#endif + #ifndef uint16 typedef unsigned short uint16; #endif @@ -416,7 +420,7 @@ typedef struct gid_info } DOM_GID; -/* RPC_HEADER - ms rpc header */ +/* RPC_HDR - ms rpc header */ typedef struct rpc_hdr_info { uint8 major; /* 5 - RPC major version */ @@ -431,7 +435,7 @@ typedef struct rpc_hdr_info uint16 context_id; /* 0 - presentation context identifier */ uint8 cancel_count; /* 0 - cancel count */ uint8 reserved; /* 0 - reserved */ -} RPC_HEADER; +} RPC_HDR; struct smb_passwd { diff --git a/source/lib/util.c b/source/lib/util.c index 01e2dae154c..c5cfdd99f75 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4182,6 +4182,80 @@ enum remote_arch_types get_remote_arch() return ra_type; } + +/******************************************************************* +skip past some unicode strings in a buffer +********************************************************************/ +char *skip_unicode_string(char *buf,int n) +{ + while (n--) + { + while (*buf) + buf += 2; + buf += 2; + } + return(buf); +} + +/******************************************************************* +Return a ascii version of a unicode string +Hack alert: uses fixed buffer and only handles ascii strings +********************************************************************/ +#define MAXUNI 1024 +char *unistr(char *buf) +{ + static char lbufs[8][MAXUNI]; + static int nexti; + char *lbuf = lbufs[nexti]; + char *p; + nexti = (nexti+1)%8; + for (p = lbuf; *buf && p -lbuf < MAXUNI-2; p++, buf += 2) + *p = *buf; + *p = 0; + return lbuf; +} + +/******************************************************************* +strncpy for unicode strings +********************************************************************/ +int unistrncpy(char *dst, char *src, int len) +{ + int num_wchars = 0; + + while (*src && len > 0) + { + *dst++ = *src++; + *dst++ = *src++; + len--; + num_wchars++; + } + *dst++ = 0; + *dst++ = 0; + + return num_wchars; +} + + +/******************************************************************* +strcpy for unicode strings. returns length (in num of wide chars) +********************************************************************/ +int unistrcpy(char *dst, char *src) +{ + int num_wchars = 0; + + while (*src) + { + *dst++ = *src++; + *dst++ = *src++; + num_wchars++; + } + *dst++ = 0; + *dst++ = 0; + + return num_wchars; +} + + /******************************************************************* safe string copy into a fstring ********************************************************************/ @@ -4231,3 +4305,42 @@ void pstrcpy(char *dest, char *src) strlen(src))); } } + + +/******************************************************************* +align a pointer to a multiple of 4 bytes +********************************************************************/ +char *align4(char *q, char *base) +{ + if ((q - base) & 3) + { + q += 4 - ((q - base) & 3); + } + return q; +} + +/******************************************************************* +align a pointer to a multiple of 2 bytes +********************************************************************/ +char *align2(char *q, char *base) +{ + if ((q - base) & 1) + { + q++; + } + return q; +} + +/******************************************************************* +align a pointer to a multiple of align_offset bytes. looks like it +will work for offsets of 0, 2 and 4... +********************************************************************/ +char *align_offset(char *q, char *base, int align_offset) +{ + if (align_offset != 0 && ((q - base) & (align_offset-1))) + { + q += align_offset - ((q - base) & (align_offset)); + } + return q; +} + diff --git a/source/smbparse.c b/source/smbparse.c index bff1a1453a4..d39f18de5f4 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -354,21 +354,32 @@ char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align) return q; } -#if 0 /******************************************************************* -reads or writes a structure. +reads or writes an RPC_HDR structure. ********************************************************************/ - char* smb_io_(BOOL io, *, char *q, char *base, int align) +char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) { - if (== NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, , 0); q += 4; + if (rpc == NULL) return NULL; + + /* reserved should be zero: enforce it */ + rpc->reserved = 0; + + RW_CVAL(io, q, rpc->major, 0); q++; + RW_CVAL(io, q, rpc->minor, 0); q++; + RW_CVAL(io, q, rpc->pkt_type, 0); q++; + RW_CVAL(io, q, rpc->frag, 0); q++; + RW_IVAL(io, q, rpc->pack_type, 0); q += 4; + RW_SVAL(io, q, rpc->frag_len, 0); q += 2; + RW_SVAL(io, q, rpc->auth_len, 0); q += 2; + RW_IVAL(io, q, rpc->call_id, 0); q += 4; + RW_SVAL(io, q, rpc->alloc_hint, 0); q += 2; + RW_CVAL(io, q, rpc->context_id, 0); q++; + RW_CVAL(io, q, rpc->reserved, 0); q++; return q; } +#if 0 /******************************************************************* reads or writes a structure. ********************************************************************/ -- cgit From 095edfca783a6f99eb7897d4c925ce8bc1ea0a3e Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 5 Oct 1997 11:56:08 +0000 Subject: smb.h: added more structures, this time for the use in the query and response of the LSA_XXXX functions. next target: the NTLOGON mailslots (10 minutes work). smbparse.c: tidying. adding some more sub-structure functions. --- source/include/smb.h | 377 ++++++++++++++++++++++++++++++++++++++++++++++++++- source/smbparse.c | 32 ++++- 2 files changed, 403 insertions(+), 6 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index b999c136677..eb20a16cd30 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -257,10 +257,14 @@ typedef fstring string; /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ -typedef uint32 UTIME; +typedef struct time_info +{ + uint32 time; + +} UTIME; /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ -typedef struct nttime +typedef struct nttime_info { uint32 low; uint32 high; @@ -348,10 +352,17 @@ typedef struct log_info } DOM_LOG_INFO; -/* DOM_CREDs - client or server credentials */ -typedef struct cred_info +/* DOM_CHAL - challenge info */ +typedef struct chal_info { uint8 data[8]; /* credentials */ + +} DOM_CHAL; + +/* DOM_CREDs - timestamped client or server credentials */ +typedef struct cred_info +{ + DOM_CHAL challenge; /* credentials */ UTIME timestamp; /* credential time-stamp */ } DOM_CRED; @@ -437,6 +448,364 @@ typedef struct rpc_hdr_info uint8 reserved; /* 0 - reserved */ } RPC_HDR; +/* DOM_QUERY_5 - info class 5 LSA Query response */ +typedef struct dom_query_5_info +{ + uint16 uni_dom_max_len; /* domain name string length * 2 */ + uint16 uni_dom_str_len; /* domain name string length * 2 */ + uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ + uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ + UNISTR uni_domain_name; /* domain name (unicode string) */ + DOM_SID dom_sid; /* domain SID */ + +} DOM_QUERY_5; + +/* level 5 is same as level 3. we hope. */ +typedef DOM_QUERY_5 DOM_QUERY_3; + +/* LSA_POL_HND */ +typedef struct lsa_policy_info +{ + uint8 data[20]; /* policy handle */ + +} LSA_POL_HND; + + +/* LSA_Q_QUERY_INFO - LSA query info policy */ +typedef struct lsa_query_info +{ + uint16 info_class; /* info class (also a policy handle?) */ + +} LSA_Q_QUERY_INFO; + +/* LSA_R_QUERY_INFO - response to LSA query info policy */ +typedef struct lsa_r_query_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer */ + uint16 info_class; /* info class (same as info class in request) */ + + union + { + DOM_QUERY_3 id3; + DOM_QUERY_5 id5; + } dom; + +} LSA_R_QUERY_INFO; + +#define MAX_REF_DOMAINS 10 + +/* DOM_R_REF */ +typedef struct dom_ref_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer. */ + uint32 num_ref_doms_1; /* num referenced domains? */ + uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */ + uint32 max_entries; /* 32 - max number of entries */ + uint32 num_ref_doms_2; /* 4 - num referenced domains? */ + + UNIHDR2 hdr_dom_name; /* domain name unicode string header */ + UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */ + + UNISTR uni_dom_name; /* domain name unicode string */ + DOM_SID uni_dom_sid; /* domain SID */ + DOM_SID uni_ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ + +} DOM_R_REF; + +#define MAX_LOOKUP_SIDS 10 + +/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */ +typedef struct lsa_q_lookup_sids +{ + + LSA_POL_HND pol_hnd; /* policy handle */ + uint32 num_entries; + uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ + uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ + uint32 buffer_lookup_sids[MAX_LOOKUP_SIDS]; /* undocumented domain SID pointers to be looked up. */ + DOM_SID dom_sids[MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */ + uint8 undoc[16]; /* completely undocumented 16 bytes */ + +} LSA_Q_LOOKUP_SIDS; + +/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */ +typedef struct lsa_r_lookup_sids +{ + DOM_R_REF dom_ref; /* domain reference info */ + + uint32 num_entries; + uint32 undoc_buffer2; /* undocumented buffer pointer */ + uint32 num_entries2; + + DOM_SID2 dom_sid[MAX_LOOKUP_SIDS]; /* domain SIDs being looked up */ + + uint32 num_entries3; + +} LSA_R_LOOKUP_SIDS; + +/* DOM_NAME - XXXX not sure about this structure */ +typedef struct dom_name_info +{ + uint32 uni_str_len; + uint16 buffer[MAX_UNISTRLEN]; + +} DOM_NAME; + + +#define UNKNOWN_LEN 1 + +/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */ +typedef struct lsa_q_lookup_rids +{ + + LSA_POL_HND pol_hnd; /* policy handle */ + uint32 num_entries; + uint32 num_entries2; + uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ + uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ + DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */ + uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */ + +} LSA_Q_LOOKUP_RIDS; + +/* LSA_R_LOOKUP_RIDS - response to LSA Lookup Names */ +typedef struct lsa_r_lookup_rids +{ + + uint32 num_entries; + uint32 undoc_buffer2; /* undocumented buffer pointer */ + + uint32 num_entries2; + DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ + + uint32 num_entries3; + +} LSA_R_LOOKUP_RIDS; + + + +/* NEG_FLAGS */ +typedef struct lsa_neg_flags_info +{ + uint32 neg_flags; /* negotiated flags */ + +} NEG_FLAGS; + + +/* LSA_Q_REQ_CHAL */ +typedef struct lsa_q_req_chal_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_clnt; /* logon client unicode string */ + DOM_CHAL clnt_chal; /* client challenge */ + +} LSA_Q_REQ_CHAL; + + +/* LSA_R_REQ_CHAL */ +typedef struct lsa_r_req_chal_info +{ + DOM_CHAL srv_chal; /* server challenge */ + +} LSA_R_REQ_CHAL; + + + +/* LSA_Q_AUTH_2 */ +typedef struct lsa_q_auth2_info +{ + DOM_LOG_INFO clnt_id; /* client identification info */ + DOM_CHAL clnt_chal; /* client-calculated credentials */ + + NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ + +} LSA_Q_AUTH_2; + + +/* LSA_R_AUTH_2 */ +typedef struct lsa_r_auth2_info +{ + DOM_CHAL srv_chal; /* server-calculated credentials */ + NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ + +} LSA_R_AUTH_2; + + +/* LSA_Q_SRV_PWSET */ +typedef struct lsa_q_srv_pwset_info +{ + DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ + char pwd[16]; /* new password - undocumented. */ + +} LSA_Q_SRV_PWSET; + +/* LSA_R_SRV_PWSET */ +typedef struct lsa_r_srv_pwset_info +{ + DOM_CHAL srv_chal; /* server-calculated credentials */ + +} LSA_R_SRV_PWSET; + +#define LSA_MAX_GROUPS 32 + +/* LSA_USER_INFO */ +typedef struct lsa_q_user_info +{ + uint32 undoc_buffer; + + NTTIME logon_time; /* logon time */ + NTTIME logoff_time; /* logoff time */ + NTTIME kickoff_time; /* kickoff time */ + NTTIME pass_last_set_time; /* password last set time */ + NTTIME pass_can_change_time; /* password can change time */ + NTTIME pass_must_change_time; /* password must change time */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNIHDR hdr_full_name; /* user's full name unicode string header */ + UNIHDR hdr_logon_script; /* logon script unicode string header */ + UNIHDR hdr_profile_path; /* profile path unicode string header */ + UNIHDR hdr_home_dir; /* home directory unicode string header */ + UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ + + uint16 logon_count; /* logon count */ + uint16 bad_pw_count; /* bad password count */ + + uint32 user_id; /* User ID */ + uint32 group_id; /* Group ID */ + uint32 num_groups; /* num groups */ + uint32 buffer_groups; /* undocumented buffer pointer to groups. */ + uint32 user_flgs; /* user flags */ + + char sess_key[16]; /* unused user session key */ + + UNIHDR hdr_logon_srv; /* logon server unicode string header */ + UNIHDR hdr_logon_dom; /* logon domain unicode string header */ + + uint32 buffer_dom_id; /* undocumented logon domain id pointer */ + char padding[40]; /* unused padding bytes? */ + + uint32 num_sids; /* 0 - num_sids */ + uint32 buffer_sids; /* NULL - undocumented pointer to SIDs. */ + + UNISTR2 uni_user_name; /* username unicode string */ + UNISTR2 uni_full_name; /* user's full name unicode string */ + UNISTR2 uni_logon_script; /* logon script unicode string */ + UNISTR2 uni_profile_path; /* profile path unicode string */ + UNISTR2 uni_home_dir; /* home directory unicode string */ + UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + + uint32 num_groups2; /* num groups */ + DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ + + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_dom; /* logon domain unicode string */ + + DOM_SID undoc_dom_sids[2]; /* undocumented - domain SIDs */ + DOM_SID dom_sid; /* domain SID */ + +} LSA_USER_INFO; + + +/* LSA_Q_SAM_LOGON */ +typedef struct lsa_q_sam_logon_info +{ + DOM_SAM_INFO sam_id; + +} LSA_Q_SAM_LOGON; + +/* LSA_R_SAM_LOGON */ +typedef struct lsa_r_sam_logon_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + + uint32 buffer_user; + LSA_USER_INFO user; + + uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + +} LSA_R_SAM_LOGON; + + +/* LSA_Q_SAM_LOGOFF */ +typedef struct lsa_q_sam_logoff_info +{ + DOM_SAM_INFO sam_id; + +} LSA_Q_SAM_LOGOFF; + +/* LSA_R_SAM_LOGOFF */ +typedef struct lsa_r_sam_logoff_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + +} LSA_R_SAM_LOGOFF; + +/* + +Yet to be turned into structures: + +6) \\MAILSLOT\NET\NTLOGON +------------------------- + +6.1) Query for PDC +------------------ + +Request: + + uint16 0x0007 - Query for PDC + STR machine name + STR response mailslot + uint8[] padding to 2-byte align with start of mailslot. + UNISTR machine name + uint32 NTversion + uint16 LMNTtoken + uint16 LM20token + +Response: + + uint16 0x000A - Respose to Query for PDC + STR machine name (in uppercase) + uint8[] padding to 2-byte align with start of mailslot. + UNISTR machine name + UNISTR domain name + uint32 NTversion (same as received in request) + uint16 LMNTtoken (same as received in request) + uint16 LM20token (same as received in request) + + +6.2) SAM Logon +-------------- + +Request: + + uint16 0x0012 - SAM Logon + uint16 request count + UNISTR machine name + UNISTR user name + STR response mailslot + uint32 alloweable account + uint32 domain SID size + char[sid_size] domain SID, of sid_size bytes. + uint8[] ???? padding to 4? 2? -byte align with start of mailslot. + uint32 NTversion + uint16 LMNTtoken + uint16 LM20token + +Response: + + uint16 0x0013 - Response to SAM Logon + UNISTR machine name + UNISTR user name - workstation trust account + UNISTR domain name + uint32 NTversion + uint16 LMNTtoken + uint16 LM20token + +*/ + struct smb_passwd { int smb_userid; diff --git a/source/smbparse.c b/source/smbparse.c index d39f18de5f4..869aab21c1e 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -24,6 +24,20 @@ extern int DEBUGLEVEL; +/******************************************************************* +reads or writes a UTIME type. +********************************************************************/ +char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align) +{ + if (t == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL (io, q, t->time, 0); q += 4; + + return q; +} + /******************************************************************* reads or writes an NTTIME structure. ********************************************************************/ @@ -222,6 +236,20 @@ char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align return q; } +/******************************************************************* +reads or writes a DOM_CHAL structure. +********************************************************************/ +char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align) +{ + if (chal == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_PCVAL(io, q, chal->data, 8); q += 8; + + return q; +} + /******************************************************************* reads or writes a DOM_CRED structure. ********************************************************************/ @@ -231,8 +259,8 @@ char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align) q = align_offset(q, base, align); - RW_PCVAL(io, q, cred->data, 8); q += 8; - RW_IVAL (io, q, cred->timestamp, 0); q += 4; + q = smb_io_chal (io, &(cred->challenge), q, base, align); + q = smb_io_utime(io, &(cred->timestamp), q, base, align); return q; } -- cgit From 369f7d41d6ff6d2b9b8c1e0cac99d0f0d03410b0 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 5 Oct 1997 12:39:51 +0000 Subject: processes LSA queries and responses to/from RPC data stream into structures. --- source/lsaparse.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 source/lsaparse.c diff --git a/source/lsaparse.c b/source/lsaparse.c new file mode 100644 index 00000000000..52c9335cd03 --- /dev/null +++ b/source/lsaparse.c @@ -0,0 +1,88 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba utility functions + Copyright (C) Luke Leighton 1996 - 1997 + + 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 DEBUGLEVEL; + + +/******************************************************************* +reads or writes an LSA_Q_QUERY_INFO structure. +********************************************************************/ +char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align) +{ + if (q_q == NULL) return NULL; + + RW_SVAL(io, q, q_q->info_class, 0); q += 2; + + return q; +} + +/******************************************************************* +reads or writes an LSA_Q_QUERY_INFO structure. +********************************************************************/ +char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align) +{ + if (r_q == NULL) return NULL; + + RW_IVAL(io, q, r_q->undoc_buffer, 0); q += 4; + + if (r_q->undoc_buffer != 0) + { + RW_SVAL(io, q, r_q->info_class, 0); q += 2; + + switch (r_q->info_class) + { + case 3: + { + q = smb_io_dom_query_3(io, &(r_q->dom.id3), q, base, align); + break; + } + case 5: + { + q = smb_io_dom_query_5(io, &(r_q->dom.id3), q, base, align); + break; + } + default: + { + /* PANIC! */ + break; + } + } + } + return q; +} + +#if 0 +/******************************************************************* +reads or writes a structure. +********************************************************************/ + char* smb_io_(BOOL io, *, char *q, char *base, int align) +{ + if (== NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, , 0); q += 4; + + return q; +} +#endif -- cgit From 2f722fe289051558dbe77aeb0a830bb3ded10a83 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sun, 5 Oct 1997 14:17:53 +0000 Subject: updating lsa and smb parsing routines and structures. --- source/include/proto.h | 32 +++++++++++++++++ source/include/smb.h | 23 +++++++++---- source/lsaparse.c | 15 +++++++- source/smbparse.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 155 insertions(+), 8 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 4ec4a42f2aa..705b08b633c 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -310,6 +310,11 @@ void del_share_mode(share_lock_token token, int fnum); BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type); BOOL remove_share_oplock(int fnum, share_lock_token token); +/*The following definitions come from lsaparse.c */ + +char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align); +char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align); + /*The following definitions come from mangle.c */ int str_checksum(char *s); @@ -772,6 +777,33 @@ void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24); void E_md4hash(uchar *passwd, uchar *p16); void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24); +/*The following definitions come from smbparse.c */ + +char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align); +char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align); +char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align); +char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align); +char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align); +char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align); +char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align); +char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align); +char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align); +char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align); +char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align); +char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align); +char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align); +char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align); +char* smb_io_rc4_owf(BOOL io, RC4_OWF *hash, char *q, char *base, int align); +char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align); +char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align); +char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align); +char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align); +char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align); +char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); +char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); +char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align); +char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align); + /*The following definitions come from smbpass.c */ int pw_file_lock(char *name, int type, int secs); diff --git a/source/include/smb.h b/source/include/smb.h index eb20a16cd30..a3a6d326e03 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -331,6 +331,16 @@ typedef struct domsid2_info } DOM_SID2; +/* DOM_SID3 - domain SID structure - SIDs stored in unicode */ +typedef struct domsid3_info +{ + UNISTR str; /* domain SID unicode string */ + uint32 undoc; /* value is 0 */ + uint32 type1; /* value is 1 */ + uint32 type2; /* value is 5 or 3 */ + +} DOM_SID3; + /* DOM_RID2 - domain RID structure */ typedef struct domrid2_info { @@ -446,10 +456,11 @@ typedef struct rpc_hdr_info uint16 context_id; /* 0 - presentation context identifier */ uint8 cancel_count; /* 0 - cancel count */ uint8 reserved; /* 0 - reserved */ + } RPC_HDR; -/* DOM_QUERY_5 - info class 5 LSA Query response */ -typedef struct dom_query_5_info +/* DOM_QUERY - info class 3 and 5 LSA Query response */ +typedef struct dom_query_info { uint16 uni_dom_max_len; /* domain name string length * 2 */ uint16 uni_dom_str_len; /* domain name string length * 2 */ @@ -458,10 +469,11 @@ typedef struct dom_query_5_info UNISTR uni_domain_name; /* domain name (unicode string) */ DOM_SID dom_sid; /* domain SID */ -} DOM_QUERY_5; +} DOM_QUERY; /* level 5 is same as level 3. we hope. */ -typedef DOM_QUERY_5 DOM_QUERY_3; +typedef DOM_QUERY DOM_QUERY_3; +typedef DOM_QUERY DOM_QUERY_5; /* LSA_POL_HND */ typedef struct lsa_policy_info @@ -507,8 +519,7 @@ typedef struct dom_ref_info UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */ UNISTR uni_dom_name; /* domain name unicode string */ - DOM_SID uni_dom_sid; /* domain SID */ - DOM_SID uni_ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ + DOM_SID ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ } DOM_R_REF; diff --git a/source/lsaparse.c b/source/lsaparse.c index 52c9335cd03..0e38c8a6670 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -75,7 +75,20 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al /******************************************************************* reads or writes a structure. ********************************************************************/ - char* smb_io_(BOOL io, *, char *q, char *base, int align) + char* lsa_io_(BOOL io, *, char *q, char *base, int align) +{ + if (== NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, , 0); q += 4; + + return q; +} +/******************************************************************* +reads or writes a structure. +********************************************************************/ + char* lsa_io_(BOOL io, *, char *q, char *base, int align) { if (== NULL) return NULL; diff --git a/source/smbparse.c b/source/smbparse.c index 869aab21c1e..e109f09a6f6 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -56,7 +56,7 @@ char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_SID structure. ********************************************************************/ -char* smb_io_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) +char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) { int i; @@ -407,6 +407,97 @@ char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) return q; } +/******************************************************************* +reads or writes an LSA_POL_HND structure. +********************************************************************/ +char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align) +{ + if (pol == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_PCVAL(io, q, pol->data, 20); q += 20; + + return q; +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) +{ + return smb_io_dom_query(io, d_q, q, base, align); +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) +{ + return smb_io_dom_query(io, d_q, q, base, align); +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) +{ + if (d_q == NULL) return NULL; + + q = align_offset(q, base, align); + + + RW_SVAL(io, q, d_q->uni_dom_max_len, 0); q += 2; /* domain name string length * 2 */ + RW_SVAL(io, q, d_q->uni_dom_str_len, 0); q += 2; /* domain name string length * 2 */ + + RW_IVAL(io, q, d_q->buffer_dom_name, 0); q += 4; /* undocumented domain name string buffer pointer */ + RW_IVAL(io, q, d_q->buffer_dom_sid , 0); q += 4; /* undocumented domain SID string buffer pointer */ + + if (d_q->buffer_dom_name != 0) + { + q = smb_io_unistr(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ + } + if (d_q->buffer_dom_sid != 0) + { + q = smb_io_dom_sid(io, &(d_q->dom_sid), q, base, align); /* domain SID */ + } + + return q; +} + +/******************************************************************* +reads or writes a DOM_R_REF structure. +********************************************************************/ +char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align) +{ + int i; + + if (r_r == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; /* undocumented buffer pointer. */ + RW_IVAL(io, q, r_r->num_ref_doms_1, 0); q += 4; /* num referenced domains? */ + RW_IVAL(io, q, r_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer. */ + RW_IVAL(io, q, r_r->max_entries, 0); q += 4; /* 32 - max number of entries */ + RW_IVAL(io, q, r_r->num_ref_doms_2, 0); q += 4; /* 4 - num referenced domains? */ + + q = smb_io_unihdr2(io, &(r_r->hdr_dom_name), q, base, align); /* domain name unicode string header */ + + for (i = 0; i < r_r->num_ref_doms_1-1; i++) + { + q = smb_io_unihdr2(io, &(r_r->hdr_ref_dom[i]), q, base, align); + } + + q = smb_io_unistr(io, &(r_r->uni_dom_name), q, base, align); /* domain name unicode string */ + + for (i = 0; i < r_r->num_ref_doms_2; i++) + { + q = smb_io_dom_sid(io, &(r_r->ref_dom[i]), q, base, align); /* referenced domain SIDs */ + } + return q; +} + #if 0 /******************************************************************* reads or writes a structure. -- cgit From a1c718728c46ebf8916af8985b4dae4d099f4ec2 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 6 Oct 1997 13:30:54 +0000 Subject: Makefile: added lsaparse.c and smbparse.c lsaparse.c, smbparse.c, smb.h: more functions / structures. proto.h: the usual. --- source/include/proto.h | 13 ++ source/include/smb.h | 9 +- source/lsaparse.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++++- source/smbparse.c | 37 ++++- 4 files changed, 442 insertions(+), 4 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 705b08b633c..a6250ca56c8 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -314,6 +314,17 @@ BOOL remove_share_oplock(int fnum, share_lock_token token); char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align); char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align); +char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align); +char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align); +char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align); +char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align); +char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align); +char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align); +char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align); +char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align); +char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align); +char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align); +char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align); /*The following definitions come from mangle.c */ @@ -803,6 +814,8 @@ char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int ali char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align); char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align); +char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align); +char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align); /*The following definitions come from smbpass.c */ diff --git a/source/include/smb.h b/source/include/smb.h index a3a6d326e03..280147b41f9 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -545,7 +545,7 @@ typedef struct lsa_r_lookup_sids DOM_R_REF dom_ref; /* domain reference info */ uint32 num_entries; - uint32 undoc_buffer2; /* undocumented buffer pointer */ + uint32 undoc_buffer; /* undocumented buffer pointer */ uint32 num_entries2; DOM_SID2 dom_sid[MAX_LOOKUP_SIDS]; /* domain SIDs being looked up */ @@ -558,7 +558,11 @@ typedef struct lsa_r_lookup_sids typedef struct dom_name_info { uint32 uni_str_len; +#if 1 /* don't know if buffer is null-terminated */ + UNISTR buffer; +#else /* or length indicated by uni_str_len member */ uint16 buffer[MAX_UNISTRLEN]; +#endif } DOM_NAME; @@ -582,9 +586,10 @@ typedef struct lsa_q_lookup_rids /* LSA_R_LOOKUP_RIDS - response to LSA Lookup Names */ typedef struct lsa_r_lookup_rids { + DOM_R_REF dom_ref; /* domain reference info */ uint32 num_entries; - uint32 undoc_buffer2; /* undocumented buffer pointer */ + uint32 undoc_buffer; /* undocumented buffer pointer */ uint32 num_entries2; DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ diff --git a/source/lsaparse.c b/source/lsaparse.c index 0e38c8a6670..68884833f4c 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Samba utility functions - Copyright (C) Luke Leighton 1996 - 1997 + Copyright (C) Luke Leighton 1996 - 1997 Paul Ashton 1997 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 @@ -71,6 +71,285 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al return q; } +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align) +{ + int i; + + if (q_s == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align); /* policy handle */ + + RW_IVAL(io, q, q_s->num_entries, 0); q += 4; + RW_IVAL(io, q, q_s->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ + RW_IVAL(io, q, q_s->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ + + for (i = 0; i < q_s->num_entries; i++) + { + RW_IVAL(io, q, q_s->buffer_lookup_sids[i], 0); q += 4; /* undocumented domain SID pointers to be looked up. */ + } + + for (i = 0; i < q_s->num_entries; i++) + { + q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align); /* domain SIDs to be looked up. */ + } + + RW_PCVAL(io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align) +{ + int i; + + if (r_s == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align); /* domain reference info */ + + RW_IVAL(io, q, r_s->num_entries, 0); q += 4; + RW_IVAL(io, q, r_s->undoc_buffer, 0); q += 4; + RW_IVAL(io, q, r_s->num_entries2, 0); q += 4; + + for (i = 0; i < r_s->num_entries2; i++) + { + q = smb_io_dom_sid2(io, &(r_s->dom_sid[i]), q, base, align); /* domain SIDs being looked up */ + } + + RW_IVAL(io, q, r_s->num_entries3, 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align) +{ + int i; + + if (q_r == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align); /* policy handle */ + + RW_IVAL(io, q, q_r->num_entries, 0); q += 4; + RW_IVAL(io, q, q_r->num_entries2, 0); q += 4; + RW_IVAL(io, q, q_r->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ + RW_IVAL(io, q, q_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ + + for (i = 0; i < q_r->num_entries; i++) + { + q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, 0); /* names to be looked up */ + } + + RW_PCVAL(io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align) +{ + int i; + + if (r_r == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align); /* domain reference info */ + + RW_IVAL(io, q, r_r->num_entries, 0); q += 4; + RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; + RW_IVAL(io, q, r_r->num_entries2, 0); q += 4; + + for (i = 0; i < r_r->num_entries2; i++) + { + q = smb_io_dom_rid2(io, &(r_r->dom_rid[i]), q, base, align); /* domain RIDs being looked up */ + } + + RW_IVAL(io, q, r_r->num_entries3, 0); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align) +{ + if (q_c == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align); /* logon server unicode string */ + q = smb_io_unistr2(io, &(q_c->uni_logon_clnt), q, base, align); /* logon client unicode string */ + q = smb_io_chal(io, &(q_c->clnt_chal), q, base, align); /* client challenge */ + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align) +{ + if (r_c == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_chal(io, &(r_c->srv_chal), q, base, align); /* server challenge */ + + return q; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align) +{ + if (q_a == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align); /* client identification info */ + q = smb_io_chal (io, &(q_a->clnt_chal), q, base, align); /* client-calculated credentials */ + q = smb_io_neg_flags(io, &(q_a->clnt_flgs), q, base, align); + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align) +{ + if (r_a == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_chal (io, &(r_a->srv_chal), q, base, align); /* server challenge */ + q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align); + + return q; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align) +{ + if (q_s == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_clnt_info(io, &(q_s->clnt_id), q, base, align); /* client identification/authentication info */ + RW_PCVAL(io, q, q_s->pwd, 16); q += 16; /* new password - undocumented */ + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align) +{ + if (r_s == NULL) return NULL; + + q = align_offset(q, base, align); + + q = smb_io_chal(io, &(r_s->srv_chal), q, base, align); /* server challenge */ + + return q; +} + +/* LSA_USER_INFO */ + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align) +{ + int i; + + if (usr == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, usr->undoc_buffer, 0); q += 4; + + q = smb_io_time(io, &(usr->logon_time) , q, base, align); /* logon time */ + q = smb_io_time(io, &(usr->logoff_time) , q, base, align); /* logoff time */ + q = smb_io_time(io, &(usr->kickoff_time) , q, base, align); /* kickoff time */ + q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align); /* password last set time */ + q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align); /* password can change time */ + q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align); /* password must change time */ + + q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align); /* username unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align); /* user's full name unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align); /* logon script unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align); /* profile path unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align); /* home directory unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align); /* home directory drive unicode string header */ + + RW_SVAL(io, q, usr->logon_count , 0); q += 2; /* logon count */ + RW_SVAL(io, q, usr->bad_pw_count, 0); q += 2; /* bad password count */ + + RW_IVAL(io, q, usr->user_id , 0); q += 4; /* User ID */ + RW_IVAL(io, q, usr->group_id , 0); q += 4; /* Group ID */ + RW_IVAL(io, q, usr->num_groups , 0); q += 4; /* num groups */ + RW_IVAL(io, q, usr->buffer_groups, 0); q += 4; /* undocumented buffer pointer to groups. */ + RW_IVAL(io, q, usr->user_flgs , 0); q += 4; /* user flags */ + + RW_PCVAL(io, q, usr->sess_key, 16); q += 16; /* unused user session key */ + + q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align); /* logon server unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align); /* logon domain unicode string header */ + + RW_IVAL(io, q, usr->buffer_dom_id, 0); q += 4; /* undocumented logon domain id pointer */ + RW_PCVAL(io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ + + RW_IVAL(io, q, usr->num_sids, 0); q += 4; /* 0 - num_sids */ + RW_IVAL(io, q, usr->buffer_sids, 0); q += 4; /* NULL - undocumented pointer to SIDs. */ + + q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align); /* username unicode string */ + q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align); /* user's full name unicode string */ + q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align); /* logon script unicode string */ + q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align); /* profile path unicode string */ + q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align); /* home directory unicode string */ + q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align); /* home directory drive unicode string */ + + RW_IVAL(io, q, usr->num_groups2, 0); q += 4; /* num groups */ + for (i = 0; i < usr->num_groups2; i++) + { + q = smb_io_gid(io, &(usr->gids[i]), q, base, align); /* group info */ + } + + q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align); /* logon server unicode string */ + q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align); /* logon domain unicode string */ + + q = smb_io_dom_sid(io, &(usr->undoc_dom_sids[0]), q, base, align); /* undocumented - domain SIDs */ + q = smb_io_dom_sid(io, &(usr->undoc_dom_sids[1]), q, base, align); /* undocumented - domain SIDs */ + q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align); /* domain SID */ + + return q; +} + + #if 0 /******************************************************************* reads or writes a structure. @@ -85,6 +364,112 @@ reads or writes a structure. return q; } +#endif + + +#if 0 /* to be done... */ + + +#define LSA_MAX_GROUPS 32 + +/* LSA_USER_INFO */ +typedef struct lsa_q_user_info +{ + uint32 undoc_buffer; + + NTTIME logon_time; /* logon time */ + NTTIME logoff_time; /* logoff time */ + NTTIME kickoff_time; /* kickoff time */ + NTTIME pass_last_set_time; /* password last set time */ + NTTIME pass_can_change_time; /* password can change time */ + NTTIME pass_must_change_time; /* password must change time */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNIHDR hdr_full_name; /* user's full name unicode string header */ + UNIHDR hdr_logon_script; /* logon script unicode string header */ + UNIHDR hdr_profile_path; /* profile path unicode string header */ + UNIHDR hdr_home_dir; /* home directory unicode string header */ + UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ + + uint16 logon_count; /* logon count */ + uint16 bad_pw_count; /* bad password count */ + + uint32 user_id; /* User ID */ + uint32 group_id; /* Group ID */ + uint32 num_groups; /* num groups */ + uint32 buffer_groups; /* undocumented buffer pointer to groups. */ + uint32 user_flgs; /* user flags */ + + char sess_key[16]; /* unused user session key */ + + UNIHDR hdr_logon_srv; /* logon server unicode string header */ + UNIHDR hdr_logon_dom; /* logon domain unicode string header */ + + uint32 buffer_dom_id; /* undocumented logon domain id pointer */ + char padding[40]; /* unused padding bytes? */ + + uint32 num_sids; /* 0 - num_sids */ + uint32 buffer_sids; /* NULL - undocumented pointer to SIDs. */ + + UNISTR2 uni_user_name; /* username unicode string */ + UNISTR2 uni_full_name; /* user's full name unicode string */ + UNISTR2 uni_logon_script; /* logon script unicode string */ + UNISTR2 uni_profile_path; /* profile path unicode string */ + UNISTR2 uni_home_dir; /* home directory unicode string */ + UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + + uint32 num_groups2; /* num groups */ + DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ + + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_dom; /* logon domain unicode string */ + + DOM_SID undoc_dom_sids[2]; /* undocumented - domain SIDs */ + DOM_SID dom_sid; /* domain SID */ + +} LSA_USER_INFO; + + +/* LSA_Q_SAM_LOGON */ +typedef struct lsa_q_sam_logon_info +{ + DOM_SAM_INFO sam_id; + +} LSA_Q_SAM_LOGON; + +/* LSA_R_SAM_LOGON */ +typedef struct lsa_r_sam_logon_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + + uint32 buffer_user; + LSA_USER_INFO user; + + uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + +} LSA_R_SAM_LOGON; + + +/* LSA_Q_SAM_LOGOFF */ +typedef struct lsa_q_sam_logoff_info +{ + DOM_SAM_INFO sam_id; + +} LSA_Q_SAM_LOGOFF; + +/* LSA_R_SAM_LOGOFF */ +typedef struct lsa_r_sam_logoff_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + +} LSA_R_SAM_LOGOFF; + +#endif + + +#if 0 /******************************************************************* reads or writes a structure. ********************************************************************/ diff --git a/source/smbparse.c b/source/smbparse.c index e109f09a6f6..c44c41c4cd9 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Samba utility functions - Copyright (C) Luke Leighton 1996 - 1997 + Copyright (C) Luke Leighton 1996 - 1997 Paul Ashton 1997 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 @@ -498,6 +498,41 @@ char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align) return q; } +/******************************************************************* +reads or writes a DOM_NAME structure. +********************************************************************/ +char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align) +{ + if (name == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, name->uni_str_len, 0); q += 4; + + /* don't know if len is specified by uni_str_len member... */ + /* assume unicode string is unicode-null-terminated, instead */ + + q = smb_io_unistr(io, &(name->buffer), q, base, align); + + return q; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align) +{ + if (neg == NULL) return NULL; + + q = align_offset(q, base, align); + + RW_IVAL(io, q, neg->neg_flags, 0); q += 4; + + return q; +} + + #if 0 /******************************************************************* reads or writes a structure. -- cgit From 5bc75c6c626251dc8ba04ff4a83e81b92d93d2d6 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 6 Oct 1997 14:52:26 +0000 Subject: lsaparse.c smb.h: added 32 bit "return status" to the response structures. --- source/include/proto.h | 4 ++ source/include/smb.h | 16 ++++++ source/lsaparse.c | 146 ++++++++++++++++++------------------------------- 3 files changed, 74 insertions(+), 92 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index a6250ca56c8..9faecd3a003 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -325,6 +325,10 @@ char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align); char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align); char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align); +char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align); +char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align); +char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align); +char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align); /*The following definitions come from mangle.c */ diff --git a/source/include/smb.h b/source/include/smb.h index 280147b41f9..1b8f04f02e2 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -502,6 +502,8 @@ typedef struct lsa_r_query_info DOM_QUERY_5 id5; } dom; + uint32 status; /* return code */ + } LSA_R_QUERY_INFO; #define MAX_REF_DOMAINS 10 @@ -552,6 +554,8 @@ typedef struct lsa_r_lookup_sids uint32 num_entries3; + uint32 status; /* return code */ + } LSA_R_LOOKUP_SIDS; /* DOM_NAME - XXXX not sure about this structure */ @@ -596,6 +600,8 @@ typedef struct lsa_r_lookup_rids uint32 num_entries3; + uint32 status; /* return code */ + } LSA_R_LOOKUP_RIDS; @@ -624,6 +630,8 @@ typedef struct lsa_r_req_chal_info { DOM_CHAL srv_chal; /* server challenge */ + uint32 status; /* return code */ + } LSA_R_REQ_CHAL; @@ -645,6 +653,8 @@ typedef struct lsa_r_auth2_info DOM_CHAL srv_chal; /* server-calculated credentials */ NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ + uint32 status; /* return code */ + } LSA_R_AUTH_2; @@ -661,6 +671,8 @@ typedef struct lsa_r_srv_pwset_info { DOM_CHAL srv_chal; /* server-calculated credentials */ + uint32 status; /* return code */ + } LSA_R_SRV_PWSET; #define LSA_MAX_GROUPS 32 @@ -741,6 +753,8 @@ typedef struct lsa_r_sam_logon_info uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + uint32 status; /* return code */ + } LSA_R_SAM_LOGON; @@ -757,6 +771,8 @@ typedef struct lsa_r_sam_logoff_info uint32 buffer_creds; /* undocumented buffer pointer */ DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + uint32 status; /* return code */ + } LSA_R_SAM_LOGOFF; /* diff --git a/source/lsaparse.c b/source/lsaparse.c index 68884833f4c..70d4f493800 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -68,6 +68,9 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al } } } + + RW_IVAL(io, q, r_q->status, 0); q += 4; + return q; } @@ -127,6 +130,8 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, RW_IVAL(io, q, r_s->num_entries3, 0); q += 4; + RW_IVAL(io, q, r_s->status, 0); q += 4; + return q; } @@ -182,6 +187,8 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, RW_IVAL(io, q, r_r->num_entries3, 0); q += 4; + RW_IVAL(io, q, r_r->status, 0); q += 4; + return q; } @@ -212,6 +219,8 @@ char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int a q = smb_io_chal(io, &(r_c->srv_chal), q, base, align); /* server challenge */ + RW_IVAL(io, q, r_c->status, 0); q += 4; + return q; } @@ -244,6 +253,8 @@ char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align q = smb_io_chal (io, &(r_a->srv_chal), q, base, align); /* server challenge */ q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align); + RW_IVAL(io, q, r_a->status, 0); q += 4; + return q; } @@ -274,6 +285,8 @@ char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int q = smb_io_chal(io, &(r_s->srv_chal), q, base, align); /* server challenge */ + RW_IVAL(io, q, r_s->status, 0); q += 4; + return q; } @@ -349,125 +362,72 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali return q; } - -#if 0 /******************************************************************* reads or writes a structure. ********************************************************************/ - char* lsa_io_(BOOL io, *, char *q, char *base, int align) +char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align) { - if (== NULL) return NULL; + if (q_l == NULL) return NULL; q = align_offset(q, base, align); - RW_IVAL(io, q, , 0); q += 4; + q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ return q; } -#endif - - -#if 0 /* to be done... */ - -#define LSA_MAX_GROUPS 32 - -/* LSA_USER_INFO */ -typedef struct lsa_q_user_info +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align) { - uint32 undoc_buffer; - - NTTIME logon_time; /* logon time */ - NTTIME logoff_time; /* logoff time */ - NTTIME kickoff_time; /* kickoff time */ - NTTIME pass_last_set_time; /* password last set time */ - NTTIME pass_can_change_time; /* password can change time */ - NTTIME pass_must_change_time; /* password must change time */ + if (r_l == NULL) return NULL; - UNIHDR hdr_user_name; /* username unicode string header */ - UNIHDR hdr_full_name; /* user's full name unicode string header */ - UNIHDR hdr_logon_script; /* logon script unicode string header */ - UNIHDR hdr_profile_path; /* profile path unicode string header */ - UNIHDR hdr_home_dir; /* home directory unicode string header */ - UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ - - uint16 logon_count; /* logon count */ - uint16 bad_pw_count; /* bad password count */ - - uint32 user_id; /* User ID */ - uint32 group_id; /* Group ID */ - uint32 num_groups; /* num groups */ - uint32 buffer_groups; /* undocumented buffer pointer to groups. */ - uint32 user_flgs; /* user flags */ - - char sess_key[16]; /* unused user session key */ - - UNIHDR hdr_logon_srv; /* logon server unicode string header */ - UNIHDR hdr_logon_dom; /* logon domain unicode string header */ - - uint32 buffer_dom_id; /* undocumented logon domain id pointer */ - char padding[40]; /* unused padding bytes? */ - - uint32 num_sids; /* 0 - num_sids */ - uint32 buffer_sids; /* NULL - undocumented pointer to SIDs. */ + q = align_offset(q, base, align); - UNISTR2 uni_user_name; /* username unicode string */ - UNISTR2 uni_full_name; /* user's full name unicode string */ - UNISTR2 uni_logon_script; /* logon script unicode string */ - UNISTR2 uni_profile_path; /* profile path unicode string */ - UNISTR2 uni_home_dir; /* home directory unicode string */ - UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ + q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ - uint32 num_groups2; /* num groups */ - DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ + RW_IVAL(io, q, r_l->buffer_user, 0); q += 4; + q = lsa_io_user_info(io, &(r_l->user), q, base, align); - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_dom; /* logon domain unicode string */ + RW_IVAL(io, q, r_l->auth_resp, 0); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ - DOM_SID undoc_dom_sids[2]; /* undocumented - domain SIDs */ - DOM_SID dom_sid; /* domain SID */ + RW_IVAL(io, q, r_l->status, 0); q += 4; -} LSA_USER_INFO; - - -/* LSA_Q_SAM_LOGON */ -typedef struct lsa_q_sam_logon_info -{ - DOM_SAM_INFO sam_id; - -} LSA_Q_SAM_LOGON; + return q; +} -/* LSA_R_SAM_LOGON */ -typedef struct lsa_r_sam_logon_info +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align) { - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - uint32 buffer_user; - LSA_USER_INFO user; - - uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + if (q_l == NULL) return NULL; -} LSA_R_SAM_LOGON; + q = align_offset(q, base, align); + + q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ + return q; +} -/* LSA_Q_SAM_LOGOFF */ -typedef struct lsa_q_sam_logoff_info +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align) { - DOM_SAM_INFO sam_id; + if (r_l == NULL) return NULL; -} LSA_Q_SAM_LOGOFF; - -/* LSA_R_SAM_LOGOFF */ -typedef struct lsa_r_sam_logoff_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - -} LSA_R_SAM_LOGOFF; + q = align_offset(q, base, align); + + RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ + q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ -#endif + RW_IVAL(io, q, r_l->status, 0); q += 4; + return q; +} #if 0 /******************************************************************* @@ -484,3 +444,5 @@ reads or writes a structure. return q; } #endif + + -- cgit From b93509846d6291771787af457500eec8984ee6bd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 17:52:25 +0000 Subject: client.c: Changed shadowed variable. locking.c: Removed USE_OPLOCKS - now the default. params.c: Removed unused variable. proto.h: Updated. reply.c: Removed USE_OPLOCKS - now the default. server.c: Removed USE_OPLOCKS - now the default. smb.h: Removed USE_OPLOCKS - now the default. smbparse.c: Changed shadowed variable. status.c: Removed USE_OPLOCKS - now the default. util.c: Removed USE_OPLOCKS - now the default. Jeremy (jallison@whistle.com) --- source/client/client.c | 8 ++++---- source/include/proto.h | 4 ++-- source/include/smb.h | 24 +++++------------------- source/lib/util.c | 8 +++----- source/locking/locking.c | 18 ------------------ source/param/params.c | 1 - source/smbd/reply.c | 6 +----- source/smbd/server.c | 26 -------------------------- source/smbparse.c | 8 ++++---- source/utils/status.c | 15 ++------------- 10 files changed, 21 insertions(+), 97 deletions(-) diff --git a/source/client/client.c b/source/client/client.c index 403eea2fc99..6d85bd8807f 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -4562,12 +4562,12 @@ static void usage(char *pname) break; case 'U': { - char *p; + char *lp; strcpy(username,optarg); - if ((p=strchr(username,'%'))) + if ((lp=strchr(username,'%'))) { - *p = 0; - strcpy(password,p+1); + *lp = 0; + strcpy(password,lp+1); got_pass = True; memset(strchr(optarg,'%')+1,'X',strlen(password)); } diff --git a/source/include/proto.h b/source/include/proto.h index 9faecd3a003..202b1511504 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -808,7 +808,7 @@ char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align); char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align); char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align); char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align); -char* smb_io_rc4_owf(BOOL io, RC4_OWF *hash, char *q, char *base, int align); +char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align); char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align); char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align); char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align); @@ -1045,4 +1045,4 @@ void fstrcpy(char *dest, char *src); void pstrcpy(char *dest, char *src); char *align4(char *q, char *base); char *align2(char *q, char *base); -char *align_offset(char *q, char *base, int align_offset); +char *align_offset(char *q, char *base, int align_offset_len); diff --git a/source/include/smb.h b/source/include/smb.h index 1b8f04f02e2..43e402359f0 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -393,12 +393,12 @@ typedef struct logon_info } DOM_LOGON_ID; -/* RC4_OWF */ -typedef struct rc4_owf_info +/* ARC4_OWF */ +typedef struct arc4_owf_info { uint8 data[16]; -} RC4_OWF; +} ARC4_OWF; /* DOM_ID_INFO_1 */ @@ -409,8 +409,8 @@ typedef struct id_info_1 DOM_LOGON_ID logon_id; /* logon ID */ UNIHDR hdr_user_name; /* user name unicode header */ UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ - RC4_OWF rc4_lm_owf; /* rc4 LM OWF Password */ - RC4_OWF rc4_nt_owf; /* rc4 NT OWF Password */ + ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ + ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ UNISTR2 uni_domain_name; /* domain name unicode string */ UNISTR2 uni_user_name; /* user name unicode string */ UNISTR2 uni_workgroup_name; /* workgroup name unicode string */ @@ -1040,10 +1040,8 @@ typedef struct { smb_shm_offset_t next_share_mode_entry; int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } share_mode_entry; @@ -1052,10 +1050,8 @@ typedef struct typedef struct { int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } min_share_mode_entry; @@ -1081,11 +1077,7 @@ struct connect_record }; #ifndef LOCKING_VERSION -#ifdef USE_OPLOCKS #define LOCKING_VERSION 4 -#else /* USE_OPLOCKS */ -#define LOCKING_VERSION 3 -#endif /* USE_OPLOCKS */ #endif /* LOCKING_VERSION */ #if !defined(FAST_SHARE_MODES) @@ -1101,11 +1093,7 @@ struct connect_record #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 -#ifdef USE_OPLOCKS #define SMF_ENTRY_LENGTH 20 -#else /* USE_OPLOCKS */ -#define SMF_ENTRY_LENGTH 16 -#endif /* USE_OPLOCKS */ /* * Share mode record offsets. @@ -1116,10 +1104,8 @@ struct connect_record #define SME_SHAREMODE_OFFSET 8 #define SME_PID_OFFSET 12 -#ifdef USE_OPLOCKS #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 -#endif /* USE_OPLOCKS */ #endif /* FAST_SHARE_MODES */ diff --git a/source/lib/util.c b/source/lib/util.c index c5cfdd99f75..611794c4a86 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -2301,7 +2301,6 @@ BOOL receive_smb(int fd,char *buffer, int timeout) return(True); } -#ifdef USE_OPLOCKS /**************************************************************************** read a message from a udp fd. The timeout is in milli seconds @@ -2498,7 +2497,6 @@ BOOL receive_message_or_smb(int smbfd, int oplock_fd, return receive_local_message(oplock_fd, buffer, buffer_len, 0); } } -#endif /* USE_OPLOCKS */ /**************************************************************************** send an smb to a fd @@ -4335,11 +4333,11 @@ char *align2(char *q, char *base) align a pointer to a multiple of align_offset bytes. looks like it will work for offsets of 0, 2 and 4... ********************************************************************/ -char *align_offset(char *q, char *base, int align_offset) +char *align_offset(char *q, char *base, int align_offset_len) { - if (align_offset != 0 && ((q - base) & (align_offset-1))) + if (align_offset_len != 0 && ((q - base) & (align_offset_len-1))) { - q += align_offset - ((q - base) & (align_offset)); + q += align_offset_len - ((q - base) & (align_offset_len)); } return q; } diff --git a/source/locking/locking.c b/source/locking/locking.c index abda5d39d47..f29c1a6105a 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -283,10 +283,8 @@ bucket %d (number of entries now = %d)\n", */ share_array[num_entries_copied].pid = entry_scanner_p->pid; share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; -#ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = entry_scanner_p->op_port; share_array[num_entries_copied].op_type = entry_scanner_p->op_type; -#endif /* USE_OPLOCKS */ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, sizeof(struct timeval)); num_entries_copied++; @@ -555,10 +553,8 @@ inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); new_entry_p->pid = getpid(); new_entry_p->share_mode = fs_p->share_mode; -#ifdef USE_OPLOCKS new_entry_p->op_port = port; new_entry_p->op_type = op_type; -#endif /* USE_OPLOCKS */ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); /* Chain onto the share_mode_record */ @@ -589,7 +585,6 @@ Remove an oplock port and mode entry from a share mode. ********************************************************************/ BOOL remove_share_oplock(int fnum, share_lock_token token) { -#ifdef USE_OPLOCKS uint32 dev, inode; smb_shm_offset_t *mode_array; unsigned int hash_entry; @@ -694,9 +689,6 @@ mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_en } return True; -#else /* USE_OPLOCKS */ - return False; -#endif /* USE_OPLOCKS */ } #else /* FAST_SHARE_MODES */ @@ -1006,10 +998,8 @@ it left a share mode entry with mode 0x%X in share file %s\n", share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); share_array[num_entries_copied].pid = pid; -#ifdef USE_OPLOCKS share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); -#endif /* USE_OPLOCKS */ num_entries_copied++; } @@ -1054,10 +1044,8 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno))); SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); -#ifdef USE_OPLOCKS SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); -#endif /* USE_OPLOCKS */ } newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); @@ -1338,10 +1326,8 @@ deleting it.\n", fname)); SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); SIVAL(p,SME_PID_OFFSET,pid); -#ifdef USE_OPLOCKS SSVAL(p,SME_PORT_OFFSET,port); SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); -#endif /* USE_OPLOCKS */ num_entries++; @@ -1392,7 +1378,6 @@ Remove an oplock port and mode entry from a share mode. ********************************************************************/ BOOL remove_share_oplock(int fnum, share_lock_token token) { -#ifdef USE_OPLOCKS pstring fname; int fd = (int)token; char *buf = 0; @@ -1504,8 +1489,5 @@ mode file %s (%s)\n", fname, strerror(errno))); return True; -#else /* USE_OPLOCKS */ - return False; -#endif /* USE_OPLOCKS */ } #endif /* FAST_SHARE_MODES */ diff --git a/source/param/params.c b/source/param/params.c index 8c41eef789f..4d1c191b479 100644 --- a/source/param/params.c +++ b/source/param/params.c @@ -441,7 +441,6 @@ static BOOL Parse( FILE *InFile, */ { int c; - char *func = "params.c:Parse() -"; c = EatWhitespace( InFile ); while( (EOF != c) && (c > 0) ) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index a8f674183c5..fa641931eb2 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -1621,7 +1621,6 @@ int reply_readbraw(char *inbuf, char *outbuf) int fd; char *fname; -#ifdef USE_OPLOCKS /* * Special check if an oplock break has been issued * and the readraw request croses on the wire, we must @@ -1635,7 +1634,6 @@ int reply_readbraw(char *inbuf, char *outbuf) DEBUG(5,("readbraw - oplock break finished\n")); return -1; } -#endif cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -3373,7 +3371,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) unsigned char locktype = CVAL(inbuf,smb_vwv3); #if 0 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); -#endif /* USE_OPLOCKS */ +#endif uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -3391,7 +3389,6 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) data = smb_buf(inbuf); -#ifdef USE_OPLOCKS /* Check if this is an oplock break on a file we have granted an oplock on. */ @@ -3432,7 +3429,6 @@ dev = %x, inode = %x\n", fnum, dev, inode)); fsp->granted_oplock = False; return -1; } -#endif /* USE_OPLOCKS */ /* Data now points at the beginning of the list of smb_unlkrng structs */ diff --git a/source/smbd/server.c b/source/smbd/server.c index 826b17121fd..4f5b01ba91e 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -84,13 +84,11 @@ int chain_fnum = -1; /* number of open connections */ static int num_connections_open = 0; -#ifdef USE_OPLOCKS /* Oplock ipc UDP socket. */ int oplock_sock = -1; uint16 oplock_port = 0; /* Current number of oplocks we have outstanding. */ int32 global_oplocks_open = 0; -#endif /* USE_OPLOCKS */ BOOL global_oplock_break = False; @@ -1487,7 +1485,6 @@ BOOL check_file_sharing(int cnum,char *fname) { min_share_mode_entry *share_entry = &old_shares[i]; -#ifdef USE_OPLOCKS /* * Break oplocks before checking share modes. See comment in * open_file_shared for details. @@ -1513,7 +1510,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); broke_oplock = True; break; } -#endif /* USE_OPLOCKS */ /* someone else has a share lock on it, check to see if we can too */ @@ -1729,7 +1725,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, { min_share_mode_entry *share_entry = &old_shares[i]; -#ifdef USE_OPLOCKS /* * By observation of NetBench, oplocks are broken *before* share * modes are checked. This allows a file to be closed by the client @@ -1759,7 +1754,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); broke_oplock = True; break; } -#endif /* USE_OPLOCKS */ /* someone else has a share lock on it, check to see if we can too */ @@ -1841,7 +1835,6 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); if (lp_share_modes(SNUM(cnum))) { uint16 port = 0; -#ifdef USE_OPLOCKS /* JRA. Currently this only services Exlcusive and batch oplocks (no other opens on this file). This needs to be extended to level II oplocks (multiple reader @@ -1862,10 +1855,6 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); port = 0; oplock_request = 0; } -#else /* USE_OPLOCKS */ - oplock_request = 0; - port = 0; -#endif /* USE_OPLOCKS */ set_share_mode(token, fnum, port, oplock_request); } @@ -2434,7 +2423,6 @@ static void process_smb(char *inbuf, char *outbuf) trans_num++; } -#ifdef USE_OPLOCKS /**************************************************************************** open the oplock IPC socket communication ****************************************************************************/ @@ -2882,8 +2870,6 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", return True; } -#endif /* USE_OPLOCKS */ - /**************************************************************************** check if a snum is in use ****************************************************************************/ @@ -4588,9 +4574,7 @@ static void process(void) int counter; int last_keepalive=0; int service_load_counter = 0; -#ifdef USE_OPLOCKS BOOL got_smb = False; -#endif /* USE_OPLOCKS */ if (deadtime <= 0) deadtime = DEFAULT_SMBD_TIMEOUT; @@ -4601,12 +4585,8 @@ static void process(void) errno = 0; for (counter=SMBD_SELECT_LOOP; -#ifdef USE_OPLOCKS !receive_message_or_smb(Client,oplock_sock, InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); -#else /* USE_OPLOCKS */ - !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); -#endif /* USE_OPLOCKS */ counter += SMBD_SELECT_LOOP) { int i; @@ -4689,14 +4669,10 @@ static void process(void) } } -#ifdef USE_OPLOCKS if(got_smb) -#endif /* USE_OPLOCKS */ process_smb(InBuffer, OutBuffer); -#ifdef USE_OPLOCKS else process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); -#endif /* USE_OPLOCKS */ } } @@ -4976,11 +4952,9 @@ static void usage(char *pname) DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } -#ifdef USE_OPLOCKS /* Setup the oplock IPC socket. */ if(!open_oplock_ipc()) exit(1); -#endif /* USE_OPLOCKS */ process(); close_sockets(); diff --git a/source/smbparse.c b/source/smbparse.c index c44c41c4cd9..95390522ff5 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -296,9 +296,9 @@ char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align } /******************************************************************* -reads or writes an RC4_OWF structure. +reads or writes an ARC4_OWF structure. ********************************************************************/ -char* smb_io_rc4_owf(BOOL io, RC4_OWF *hash, char *q, char *base, int align) +char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align) { if (hash == NULL) return NULL; @@ -326,8 +326,8 @@ char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align); q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align); - q = smb_io_rc4_owf(io, &(id->rc4_lm_owf), q, base, align); - q = smb_io_rc4_owf(io, &(id->rc4_nt_owf), q, base, align); + q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align); + q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align); q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align); q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align); diff --git a/source/utils/status.c b/source/utils/status.c index 703105012ef..4143244ab4d 100644 --- a/source/utils/status.c +++ b/source/utils/status.c @@ -148,9 +148,7 @@ locking version (was %d, should be %d).\n",fname, void *dir; char *s; #endif /* FAST_SHARE_MODES */ -#ifdef USE_OPLOCKS int oplock_type; -#endif /* USE_OPLOCKS */ int i; struct session_record *ptr; @@ -347,9 +345,7 @@ locking version (was %d, should be %d).\n",fname, t.tv_sec = entry_scanner_p->time.tv_sec; t.tv_usec = entry_scanner_p->time.tv_usec; strcpy(fname, file_scanner_p->file_name); -#ifdef USE_OPLOCKS oplock_type = entry_scanner_p->op_type; -#endif /* USE_OPLOCKS */ #else /* FAST_SHARE_MODES */ @@ -411,9 +407,7 @@ locking version (was %d, should be %d).\n",fname, t.tv_sec = IVAL(p,SME_SEC_OFFSET); t.tv_usec = IVAL(p,SME_USEC_OFFSET); -#ifdef USE_OPLOCKS oplock_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); -#endif /* USE_OPLOCKS */ #endif /* FAST_SHARE_MODES */ fname[sizeof(fname)-1] = 0; @@ -421,13 +415,8 @@ locking version (was %d, should be %d).\n",fname, if (firstopen) { firstopen=False; printf("Locked files:\n"); -#ifdef USE_OPLOCKS printf("Pid DenyMode R/W Oplock Name\n"); printf("--------------------------------------------------\n"); -#else /* USE_OPLOCKS */ - printf("Pid DenyMode R/W Name\n"); - printf("----------------------------------\n"); -#endif /* USE_OPLOCKS */ } @@ -446,7 +435,7 @@ locking version (was %d, should be %d).\n",fname, case 1: printf("WRONLY "); break; case 2: printf("RDWR "); break; } -#ifdef USE_OPLOCKS + if((oplock_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) printf("EXCLUSIVE+BATCH "); else if (oplock_type & EXCLUSIVE_OPLOCK) @@ -455,7 +444,7 @@ locking version (was %d, should be %d).\n",fname, printf("BATCH "); else printf("NONE "); -#endif /* USE_OPLOCKS */ + printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec))); #ifdef FAST_SHARE_MODES -- cgit From db4c2cb50e11d252ff3ba0e0973767e909dd33bd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 19:50:51 +0000 Subject: Finally ! Found & fixed crash bug with logging message when deleting invalid share mode entries. Thanks to berg@wienrg.aut.alcatel.at (Dietmar Berg) for the stack backtrace. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index f29c1a6105a..6e321d0626e 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -241,6 +241,7 @@ bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); { /* Delete this share mode entry */ share_mode_entry *delete_entry_p = entry_scanner_p; + int share_mode = entry_scanner_p->share_mode; if(entry_prev_p == entry_scanner_p) { @@ -271,7 +272,7 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \ bucket %d (number of entries now = %d)\n", - pid, entry_scanner_p->share_mode, dev, inode, hash_entry, + pid, share_mode, dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); smb_shm_free(smb_shm_addr2offset(delete_entry_p)); -- cgit From 1de1a22d0cd4ca1a977f35411ca57ce0768a46d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 19:54:33 +0000 Subject: locking.c: Finally fixed nasty crash bug when deleting invalid share mode entries. util.c: Tried to stop put_ip core dump seemingly caused by bad returns from gethostbyname. Jeremy (jallison@whistle.com) --- source/lib/util.c | 4 ++++ source/locking/locking.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/lib/util.c b/source/lib/util.c index 0c4999c789c..7f785332e6a 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3150,6 +3150,10 @@ uint32 interpret_addr(char *str) DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str)); return 0; } + if(hp->h_addr == NULL) { + DEBUG(3,("Get_Hostbyname: host address is invalid for host %s.\n",str)); + return 0; + } putip((char *)&res,(char *)hp->h_addr); } diff --git a/source/locking/locking.c b/source/locking/locking.c index c2a06cac75c..868902963fe 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -206,7 +206,7 @@ file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry)); { DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \ record due to old locking version %d for file dev = %d, inode = %d in hash \ -bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry)); +bucket %d\n",file_scanner_p->locking_version, dev, inode, hash_entry)); if(file_prev_p == file_scanner_p) mode_array[hash_entry] = file_scanner_p->next_offset; else @@ -241,6 +241,7 @@ bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry)); { /* Delete this share mode entry */ share_mode_entry *delete_entry_p = entry_scanner_p; + int share_mode = entry_scanner_p->share_mode; if(entry_prev_p == entry_scanner_p) { @@ -270,8 +271,8 @@ for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \ -bucket (number of entries now = %d)\n", - pid, entry_scanner_p->share_mode, dev, inode, hash_entry, +bucket %d (number of entries now = %d)\n", + pid, share_mode, dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); smb_shm_free(smb_shm_addr2offset(delete_entry_p)); -- cgit From d808df8191cdf21b011e773e6e99b0c65524253c Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 7 Oct 1997 04:47:23 +0000 Subject: Removed samba.faq from the docs directory, it was out of date. All FAQs in docs/faq. Replaced all reference to samba.canberra.edu.au/pub/samba/samba.html with samba.anu.edu.au/samba/ Replaced references to ictinus@lake.canberra.edu.au with ictinus@samba.anu.edu.au Added 3 new mirrors, Greece, Poland, Romania Paul. --- docs/announce | 2 +- docs/faq/Samba-Server-FAQ.sgml | 6 +- docs/faq/Samba-meta-FAQ-2.html | 2 +- docs/faq/Samba-meta-FAQ.sgml | 8 +- docs/faq/Samba-meta-FAQ.txt | 433 ++++++++++++++------ docs/faq/sambafaq-1.html | 2 +- docs/faq/sambafaq-3.html | 2 +- docs/faq/sambafaq.sgml | 11 +- docs/faq/sambafaq.txt | 310 +++++++------- docs/manpages/samba.7 | 2 +- docs/samba.faq | 900 ----------------------------------------- docs/textdocs/BUGS.txt | 2 +- docs/textdocs/MIRRORS.txt | 11 +- docs/textdocs/UNIX_INSTALL.txt | 2 +- 14 files changed, 506 insertions(+), 1187 deletions(-) delete mode 100644 docs/samba.faq diff --git a/docs/announce b/docs/announce index adcde8966f8..a03ddcd0e6a 100644 --- a/docs/announce +++ b/docs/announce @@ -127,7 +127,7 @@ There is also often quite a bit of discussion about Samba on the newsgroup comp.protocols.smb. A WWW site with lots of Samba info can be found at -http://samba.canberra.edu.au/pub/samba/ +http://samba.anu.edu.au/samba/ The Samba Team (Contact: samba-bugs@samba.anu.edu.au) June 1996 diff --git a/docs/faq/Samba-Server-FAQ.sgml b/docs/faq/Samba-Server-FAQ.sgml index 4887481e2b1..020d5322811 100644 --- a/docs/faq/Samba-Server-FAQ.sgml +++ b/docs/faq/Samba-Server-FAQ.sgml @@ -3,7 +3,7 @@ v 0.1 23 Aug 1997 Dan Shearer Original Samba-Client-FAQ.sgml from Paul's sambafaq.sgml v 0.2 25 Aug 1997 Dan - + v 0.3 7 Oct 1997 Paul, changed email address from ictinus@lake... to ictinus@samba.anu --> @@ -11,9 +11,9 @@ Samba Server FAQ -<author>Dan Shearer & Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Dan Shearer & Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.1, 23 Aug '97 +<date>v 0.3, 7 Oct '97 <abstract> This is the <em>Server</em> Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server diff --git a/docs/faq/Samba-meta-FAQ-2.html b/docs/faq/Samba-meta-FAQ-2.html index c5ebab7e7e4..ac760380067 100644 --- a/docs/faq/Samba-meta-FAQ-2.html +++ b/docs/faq/Samba-meta-FAQ-2.html @@ -166,7 +166,7 @@ See below for subscription information. discussion about Samba. </LI> <LI>The WWW site 'SAMBA Web Pages' at -<A HREF="http://samba.canberra.edu.au/pub/samba/samba.html">http://samba.canberra.edu.au/pub/samba/samba.html</A> includes: +<A HREF="http://samba.anu.edu.au/samba/">http://samba.anu.edu.au/samba/</A> includes: <UL> <LI>Links to man pages and documentation, including this FAQ</LI> diff --git a/docs/faq/Samba-meta-FAQ.sgml b/docs/faq/Samba-meta-FAQ.sgml index 2b54c6fa0f1..75038f19f53 100644 --- a/docs/faq/Samba-meta-FAQ.sgml +++ b/docs/faq/Samba-meta-FAQ.sgml @@ -3,15 +3,17 @@ v 0.1 23 Aug 1997 Dan Shearer Original Samba-meta-FAQ.sgml from Paul's sambafaq.sgml v 0.2 25 Aug 1997 Dan + v 0.3 7 Oct 1997 Paul + Changed samba.canberra refs to samba.anu.../samba/ --> <article> <title> Samba meta FAQ -<author>Dan Shearer & Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Dan Shearer & Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.1, 23 Aug '97 +<date>v 0.3, 7 Oct '97 <abstract> This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It @@ -286,7 +288,7 @@ See below for subscription information. discussion about Samba. <item>The WWW site 'SAMBA Web Pages' at <url -url="http://samba.canberra.edu.au/pub/samba/samba.html"> includes: +url="http://samba.anu.edu.au/samba/"> includes: <itemize> <item>Links to man pages and documentation, including this FAQ diff --git a/docs/faq/Samba-meta-FAQ.txt b/docs/faq/Samba-meta-FAQ.txt index 967dceac8de..4fb1ed65442 100644 --- a/docs/faq/Samba-meta-FAQ.txt +++ b/docs/faq/Samba-meta-FAQ.txt @@ -43,7 +43,7 @@ 2.11. Pizza supply details - 3. About CIFS and SMB + 3. About the CIFS and SMB Protocols 3.1. What is the Server Message Block (SMB) Protocol? @@ -53,7 +53,7 @@ 4. Designing A SMB and CIFS Network - 4.1. Workgroups, Browsing Domains and Authentication Domains + 4.1. Workgroups, Domains, Authentication and Browsing 4.1.1. Defining the Terms @@ -63,19 +63,16 @@ 4.2. Authentication Schemes - 4.2.1. Workgroup Mode Services - 4.2.2. Windows NT-Style Domain + 4.2.1. NIS - 4.2.3. NIS + 4.2.2. Kerberos - 4.2.4. Kerberos + 4.2.3. FTP - 4.2.5. FTP + 4.2.4. Default Server Method - 4.2.6. Default Server Method - - 4.2.7. Client-side Database Only + 4.2.5. Client-side Database Only 4.3. Post-Authentication: Netlogon, Logon Scripts, Profiles @@ -88,47 +85,87 @@ 11.. QQuuiicckk RReeffeerreennccee GGuuiiddeess ttoo SSaammbbaa DDooccuummeennttaattiioonn + We are endeavouring to provide links here to every major class of information about Samba or things related to Samba. We cannot list every document, but we are aiming for all documents to be at most two referrals from those listed here. This needs constant maintaining, so please send the author your feedback. + 11..11.. SSaammbbaa ffoorr tthhee IImmppaattiieenntt + You know you should read the documentation but can't wait to start? What you need to do then is follow the instructions in the following - documents, in order. This should be enough to get a _s_i_m_p_l_e site going - quickly. If you have any problems at all, refer back to this section - and do some more reading. - - 1. Getting Samba: ``Download Instructions'' - - 2. Installing Samba: making sure the binaries are in place and work. - At the moment there are two kinds of Samba server installs: Unix or - close relative <INSTALL.txt> and Others <Samba-Server- - FAQ.html#PortInfo>. Do not forget to - - 3. Debug sequence: If you think you have completed the previous step - and things aren't working properly work through the diagnosis - recipe. <DIAGNOSIS.txt> - - 4. Exporting files to SMB clients: You should read the manual pages - for smb.conf, but here is a quick answer guide. <Samba-Server- - FAQ.html#Exporting> - - 5. Controlling user access: the quickest and dirtiest way of sharing - resources is to use ``share level security.'' If you want to spend - more time and have a proper username and password database you must - read the paragraph on ``domain mode security.'' If you want - encryption (eg you are using Windows NT clients) follow the SMB - encryption instructions. <Samba-Server-FAQ.html#SMBEncryptionSteps> - 6. Browsing: if you are happy to type in "\samba-serverrename" at the - client end then do not read any further. Otherwise you need to - understand the ``browsing terminoligy'' and read <BROWSING.txt>. - - 7. Printing: See the printing quick answer guide. <Samba-Server- - FAQ.html#Printing> + documents in the order given. This should be enough to get a fairly + simple site going quickly. If you have any problems, refer back to + this meta-FAQ and follow the links to find more reading material. + + + + GGeettttiinngg SSaammbbaa:: + The fastest way to get Samba going is and install it is to have + an operating system for which the Samba team has put together an + installation package. To see if your OS is included have a look + at the directory /pub/samba/Binary_Packages/"OS_Vendor" on your + nearest mirror site <../MIRRORS>. If it is included follow the + installation instructions in the README file there and then do + some ``basic testing''. If you are not so fortunate, follow the + normal ``download instructions'' and then continue with + ``building and installing Samba''. + + + BBuuiillddiinngg aanndd IInnssttaalllliinngg SSaammbbaa:: + At the moment there are two kinds of Samba server installs + besides the prepackaged binaries mentioned in the previous step. + You need to decide if you have a Unix or close relative + <../UNIX_INSTALL.txt> or other supported operating system + <Samba-Server-FAQ.html#PortInfo>. + + + BBaassiicc TTeessttiinngg:: + Try to connect using the supplied smbclient command-line + program. You need to know the IP hostname of your server. A + service name must be defined in smb.conf, as given in the + examples (under many operating systems if there is a homes + service you can just use a valid username.) Then type smbclient + \hostnamevicename Under most Unixes you will need to put the + parameters within quotation marks. If this works, try connecting + from one of the SMB clients you were planning to use with Samba. + + + DDeebbuugg sseeqquueennccee:: + If you think you have completed the previous step and things + aren't working properly work through the diagnosis recipe. + <../DIAGNOSIS.txt> + + + EExxppoorrttiinngg ffiilleess ttoo SSMMBB cclliieennttss:: + You should read the manual pages for smb.conf, but here is a + quick answer guide. <Samba-Server-FAQ.html#Exporting> + + + CCoonnttrroolllliinngg uusseerr aacccceessss:: + the quickest and dirtiest way of sharing resources is to use + ``share level security.'' If you want to spend more time and + have a proper username and password database you must read the + paragraph on ``domain mode security.'' If you want encryption + (eg you are using Windows NT clients) follow the SMB encryption + instructions. <Samba-Server-FAQ.html#SMBEncryptionSteps> + + + BBrroowwssiinngg:: + if you are happy to type in "\samba-serverrename" at the client + end then do not read any further. Otherwise you need to + understand the ``browsing terminology'' and read <Samba-Server- + FAQ.html#NameBrowsing>. + + + PPrriinnttiinngg:: + See the printing quick answer guide. <Samba-Server- + FAQ.html#Printing> + If you have got everything working to this point, you can expect Samba to be stable and secure: these are its greatest strengths. However @@ -138,8 +175,11 @@ so on are all covered either in this document or in those it refers to. + 11..22.. AAllll SSaammbbaa DDooccuummeennttaattiioonn + + +o Meta-FAQ. This is the mother of all documents, and is the one you are reading now. The latest version is always at <http://samba.anu.edu.au/[.....]> but there is probably a much @@ -151,27 +191,31 @@ from...) +o <Samba-Client-FAQ.html> is the best starting point for information - about client-side issues, includes a list of all clients that work - with Samba. + about client-side issues, includes a list of all clients that are + known to work with Samba. - +o <samba-man-index.html> contains descriptions of and links to all - the Samba manual pages, in Unix man and postscript format. + +o manual pages <samba-man-index.html> contains descriptions of and + links to all the Samba manual pages, in Unix man and postscript + format. +o <samba-txt-index.html> has descriptions of and links to a large number of text files have been contributed to samba covering many - topics. These are gradually being absorbed into the FAQs and HOWTOS + topics. These are gradually being absorbed into the FAQs and HOWTOs but in the meantime you might find helpful answers here. +o + 22.. GGeenneerraall IInnffoorrmmaattiioonn + All about Samba - what it is, how to get it, related sources of - information, how to understand the version numbering scheme, pizza - details + information, how to understand the numbering scheme, pizza details. + 22..11.. WWhhaatt iiss SSaammbbaa?? + Samba is a suite of programs which work together to allow clients to access to a server's filespace and printers via the SMB (Server Message Block) and CIFS (Common Internet Filesystem) protocols. @@ -181,6 +225,7 @@ behave much like a LAN Server, Windows NT Server or Pathworks machine, only with added functionality and flexibility designed to make life easier for administrators. + This means that using Samba you can share a server's disks and printers to many sorts of network clients, including Lan Manager, Windows for Workgroups, Windows NT, Linux, OS/2, and AIX. There is @@ -188,6 +233,10 @@ which gives a user on the server an ftp-like interface to access filespace and printers on any other SMB/CIFS servers. + SMB has been implemented over many protocols, including XNS, NBT, IPX, + NetBEUI and TCP/IP. Samba only uses TCP/IP. This is not likely to + change although there have been some requests for NetBEUI support. + Many users report that compared to other SMB implementations Samba is more stable, faster, and compatible with more clients. Administrators of some large installations say that Samba is the only SMB server @@ -206,16 +255,19 @@ versions incorporate much effort by many net.helpers. The man pages and this FAQ were originally written by Karl Auer. + 22..22.. WWhhaatt iiss tthhee ccuurrrreenntt vveerrssiioonn ooff SSaammbbaa?? + At time of writing, the current version was 1.9.17. If you want to be sure check the bottom of the change-log file. <ftp://samba.anu.edu.au/pub/samba/alpha/change-log> - For more information see ``What do the version numbers mean?'' + 22..33.. WWhheerree ccaann II ggeett iitt?? + The Samba suite is available via anonymous ftp from samba.anu.edu.au and many mirror <../MIRRORS> sites. You will get much faster performance if you use a mirror site. The latest and greatest versions @@ -235,8 +287,18 @@ binaries for that platform. The VMS, OS/2, Netware and Amiga and other ports typically have binaries made available. + A special case is vendor-provided binary packages. Samba binaries and + default configuration files are put into packages for a specific + operating system. RedHat Linux and Sun Solaris (Sparc and x86) is + already included, and others such as OS/2 may follow. All packages are + in the directory: + + /pub/samba/Binary_Packages/"OS_Vendor" + + 22..44.. WWhhaatt ddoo tthhee vveerrssiioonn nnuummbbeerrss mmeeaann?? + It is not recommended that you run a version of Samba with the word "alpha" in its name unless you know what you are doing and are willing to do some debugging. Many, many people just get the latest @@ -248,6 +310,7 @@ How the scheme works: + 1. When major changes are made the version number is increased. For example, the transition from 1.9.16 to 1.9.17. However, this version number will not appear immediately and people should @@ -269,6 +332,7 @@ So the progression goes: + 1.9.16p10 (production) 1.9.16p11 (production) 1.9.17alpha1 (test sites only) @@ -277,24 +341,30 @@ 1.9.17 (production) 1.9.17p1 (production) + + The above system means that whenever someone looks at the samba ftp site they will be able to grab the highest numbered release without an alpha in the name and be sure of getting the current recommended version. + 22..55.. WWhheerree ccaann II ggoo ffoorr ffuurrtthheerr iinnffoorrmmaattiioonn?? + There are a number of places to look for more information on Samba, including: + +o Two mailing lists devoted to discussion of Samba-related matters. See below for subscription information. +o The newsgroup comp.protocols.smb, which has a great deal of discussion about Samba. - +o The WWW site 'SAMBA Web Pages' at - <http://samba.canberra.edu.au/pub/samba/samba.html> includes: + +o The WWW site 'SAMBA Web Pages' at <http://samba.anu.edu.au/samba/> + includes: + +o Links to man pages and documentation, including this FAQ @@ -306,14 +376,22 @@ +o This FAQ and the rest in its family + + 22..66.. HHooww ddoo II ssuubbssccrriibbee ttoo tthhee SSaammbbaa MMaaiilliinngg LLiissttss?? + Send email to listproc@samba.anu.edu.au. Make sure the subject line is blank, and include the following two lines in the body of the message: + + subscribe samba Firstname Lastname subscribe samba-announce Firstname Lastname + + + Obviously you should substitute YOUR first name for "Firstname" and YOUR last name for "Lastname"! Try not to send any signature, it sometimes confuses the list processor. @@ -327,20 +405,29 @@ listproc@samba.anu.edu.au. Make sure the subject line is blank, and include the following two lines in the body of the message: + + unsubscribe samba unsubscribe samba-announce + + + The FFrroomm:: line in your message _M_U_S_T be the same address you used when you subscribed. + 22..77.. SSoommeetthhiinngg''ss ggoonnee wwrroonngg -- wwhhaatt sshhoouulldd II ddoo?? + ## ****** IIMMPPOORRTTAANNTT!! ****** ## + DO NOT post messages on mailing lists or in newsgroups until you have carried out the first three steps given here! - 1. See if there are any likely looking entries in this FAQ! If you + + 1. See if there are any likely looking entries in this FAQ! If you have just installed Samba, have you run through the checklist in DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/DIAGNOSIS.txt>? It can save you a lot of time and effort. DIAGNOSIS.txt can also be @@ -370,8 +457,12 @@ succinct description of the symptom, the problem and the solution, so that an explanation can be incorporated into the next version. + + + 22..88.. HHooww ddoo II ssuubbmmiitt ppaattcchheess oorr bbuugg rreeppoorrttss?? + If you make changes to the source code, _p_l_e_a_s_e submit these patches so that everyone else gets the benefit of your work. This is one of the most important aspects to the maintainence of Samba. Send all patches @@ -412,6 +503,7 @@ Some extras : + +o what you did and what happened +o relevant parts of a debugging output file with debuglevel higher. @@ -420,8 +512,10 @@ +o anything else you think is useful to trace down the bug + 22..99.. WWhhaatt iiff II hhaavvee aann UURRGGEENNTT mmeessssaaggee ffoorr tthhee ddeevveellooppeerrss?? + If you have spotted something very serious and believe that it is important to contact the developers quickly send a message to samba- urgent@samba.anu.edu.au. This will be processed more quickly than mail @@ -434,21 +528,25 @@ 22..1100.. WWhhaatt iiff II nneeeedd ppaaiidd--ffoorr ssuuppppoorrtt?? + Samba has a large network of consultants who provide Samba support on a commercial basis. The list is included in the package in - Support.txt, and the latest version will always be on the main samba - ftp site. Any company in the world can request that the samba team - include their details in Support.txt so we can give no guarantee of - their services. + <../Support.txt>, and the latest version will always be on the main + samba ftp site. Any company in the world can request that the samba + team include their details in Support.txt so we can give no guarantee + of their services. + 22..1111.. PPiizzzzaa ssuuppppllyy ddeettaaiillss + Those who have registered in the Samba survey as "Pizza Factory" will already know this, but the rest may need some help. Andrew doesn't ask for payment, but he does appreciate it when people give him pizza. This calls for a little organisation when the pizza donor is twenty thousand kilometres away, but it has been done. + 1. Ring up your local branch of an international pizza chain and see if they honour their vouchers internationally. Pizza Hut do, which is how the entire Canberra Linux Users Group got to eat pizza one @@ -468,7 +566,10 @@ will probably get stuck in customs or torn apart by hungry sniffer dogs but it will have been a noble gesture. - 33.. AAbboouutt CCIIFFSS aanndd SSMMBB + + 33.. AAbboouutt tthhee CCIIFFSS aanndd SSMMBB PPrroottooccoollss + + 33..11.. WWhhaatt iiss tthhee SSeerrvveerr MMeessssaaggee BBlloocckk ((SSMMBB)) PPrroottooccooll?? @@ -493,6 +594,7 @@ implement more and more of these protocols. Samba began to take a significant share of the SMB server market. + 33..22.. WWhhaatt iiss tthhee CCoommmmoonn IInntteerrnneett FFiilleessyysstteemm ((CCIIFFSS))?? The initial pressure for Microsoft to document their current SMB @@ -516,6 +618,7 @@ The following is taken from <http://www.microsoft.com/intdev/cifs/> + CIFS defines a standard remote file system access protocol for use over the Internet, enabling groups of users to work together and share documents across the Internet or within their corporate @@ -526,6 +629,8 @@ users can open and share remote files on the Internet without having to install new software or change the way they work." + + If you consider CIFS as a backwardsly-compatible refinement of SMB that will work reasonably efficiently over the Internet you won't be too far wrong. @@ -537,6 +642,7 @@ reason why a site shouldn't conduct all its file and printer sharing with CIFS and yet have no Microsoft products at all. + 33..33.. WWhhaatt iiss BBrroowwssiinngg?? The term "Browsing" causes a lot of confusion. It is the part of the @@ -549,11 +655,16 @@ subject for debate. Look at the CIFS list archives to see what the experts think. + + + 44.. DDeessiiggnniinngg AA SSMMBB aanndd CCIIFFSS NNeettwwoorrkk + The big issues for installing any network of LAN or WAN file and print servers are + +o How and where usernames, passwords and other security information is stored @@ -562,6 +673,7 @@ +o What protocols the clients can converse with + If you buy Netware, Windows NT or just about any other LAN fileserver product you are expected to lock yourself into the product's preferred answers to these questions. This tendancy is restrictive and often @@ -573,65 +685,103 @@ administators, which means allowing as many combinations of clients, servers, operating systems and protocols as possible. - 44..11.. WWoorrkkggrroouuppss,, BBrroowwssiinngg DDoommaaiinnss aanndd AAuutthheennttiiccaattiioonn DDoommaaiinnss - The concepts of a Workgroup and a Domain are fundamental to SMB - networking. Although Microsoft integrates Workgroups and Domains - tightly with their authentication procedures there is no reason why - this has to be so in an SMB network. Groups of SMB machines can work - together just as well with Unix or OS/2 Samba servers as they can with - Windows NT servers, even though the password storage and access - methods are totally different. + 44..11.. WWoorrkkggrroouuppss,, DDoommaaiinnss,, AAuutthheennttiiccaattiioonn aanndd BBrroowwssiinngg + + + From the point of view of networking implementation, Domains and + Workgroups are _e_x_a_c_t_l_y the same, except for the client logon sequence. + Some kind of distributed authentication database is associated with a + domain (there are quite a few choices) and this adds so much + flexibility that many people think of a domain as a completely + different entity to a workgroup. From Samba's point of view a client + connecting to a service presents an authentication token, and it if it + is valid they have access. Samba does not care what mechanism was used + to generate that token in the first place. + + The SMB client logging on to a domain has an expectation that every + other server in the domain should accept the same authentication + information. However the network browsing functionality of domains + and workgroups is identical and is explained in <../BROWSING.txt>. + + There are some implementation differences: Windows 95 can be a member + of both a workgroup and a domain, but Windows NT cannot. Windows 95 + also has the concept of an "alternative workgroup". Samba can only be + a member of a single workgroup or domain, although this is due to + change with a future version when nmbd will be split into two daemons, + one for WINS and the other for browsing ( <../NetBIOS.txt> explains + what WINS is.) + 44..11..11.. DDeeffiinniinngg tthhee TTeerrmmss - A Workgroup (or Browsing Domain) is collection of machines that - maintain a common database contianing information about their shared - resources. They do not necessarily have any security information in - common. The database is dynamic, modified as servers come and go on - the network and as resources are added or deleted. The term "browsing" - refers to a user accessing the database via whatever interface the - client provides. SMB servers agree between themselves as to which ones - will maintain the browsing database. Workgroups can be anywhere on a - connected TCP/IP network, including on different subnets or anywhere - on the Interet. This is a very tricky part of SMB to implement. - Due to the convoluted history of SMB there is now conflicting - terminology describing Domains and Workgroups. "Domain" is used in the - browsing specifications to define that group of servers and clients - who share a common name and a common browsing database. The following - are used exclusively in the context of Workgroup browsing: - +o Domain Master Browser - +o Local Master Browser + WWoorrkkggrroouupp + means a collection of machines that maintain a common browsing + database containing information about their shared resources. + They do not necessarily have any security information in common + (if they do, it gets called a Domain.) The browsing database is + dynamic, modified as servers come and go on the network and as + resources are added or deleted. The term "browsing" refers to a + user accessing the database via whatever interface the client + provides, eg the OS/2 Workplace Shell or Windows 95 Explorer. + SMB servers agree between themselves as to which ones will + maintain the browsing database. Workgroups can be anywhere on a + connected TCP/IP network, including on different subnets or even + on the Interet. This is a very tricky part of SMB to implement. + - Alternative terms include confusing variations such as "Browse - Master", and "Master Browser" which we are trying to eliminate from - the Samba documentation. We are moving to the use of "Browsing Domain" - wherever the word "Domain" occurs in a workgroup context. Ideally - "Workgroup" would also be replaced by Browsing Domain but it is very - widely used terminology. + MMaasstteerr BBrroowwsseerrss + are machines which holds the master browsing database for a + workgroup or domain. There are two kinds of Master Browser: - Unfortunately the group of machines which use the the Microsoft method - of sharing authentication information (but not any of the many other - methods) is also called a Domain. As explained elsewhere Microsoft are - not making this protocol public and The following are used exclusively - in the context of Microsoft Authentication domains: - +o Primary Domain Controller + +o Domain Master Browser, which holds the master browsing + information for an entire domain, which may well cross multiple + TCP/IP subnets. - +o Backup Domain Controller + +o Local Master Browser, which holds the master browsing database + for a particular subnet and communicates with the Domain Master + Browser to get information on other subnets. + + Subnets are differentiated because browsing is based on + broadcasts, and broadcasts do not pass through routers. Subnets + are not routed: while it is possible to have more than one + subnet on a single network segment this is regarded as very bad + practice. + + Master Browsers (both Domain and Local) are elected dynamically + according to an algorithm which is supposed to take into account + the machine's ability to sustain the browsing load. Samba can be + configured to always act as a master browser, ie it always wins + elections under all circumstances, even against systems such as + a Windows NT Primary Domain Controller which themselves expect + to win. + + There are also Backup Browsers which are promoted to Master + Browsers in the event of a Master Browser disappearing from the + network. + + Alternative terms include confusing variations such as "Browse + Master", and "Master Browser" which we are trying to eliminate + from the Samba documentation. + + + DDoommaaiinn CCoonnttrroolllleerr + is a term which comes from the Microsoft and IBM etc + implementation of the LAN Manager protocols. It is tied to + authentication. There are other ways of doing domain + authentication, but the Windows NT method has a large market + share. The general issues are discussed in <../DOMAIN.txt> and + a Windows NT-specific discussion is in <../DOMAIN_CONTROL.txt>. - +o Domain Logon - These terms can be very confusing, and so in the Samba documentation - we are moving to the term "Authentication Domain" wherever Domain is - used in this sense. As a final touch of irony, all Authentication - Domains are also Browsing Domains. 44..11..22.. SShhaarreelleevveell ((WWoorrkkggrroouupp)) SSeeccuurriittyy SSeerrvviicceess + With the Samba setting "security = SHARE", all shared resources information about what password is associated with them but only hints as to what usernames might be valid (the hint can be 'all users', in @@ -643,16 +793,20 @@ authentication infrastructure present or requiring them to do more than fill in a dialogue box. + 44..11..33.. AAuutthheennttiiccaattiioonn DDoommaaiinn MMooddee SSeerrvviicceess + With the Samba settings "security = USER" or "security = SERVER" accesses to all resources are checked for username/password pair - matches in a more rigorous manner. This has the effect of emulating a - Microsoft Authentication Domain. Whether or not an Authentication - Domain is involved depends on how the network has been designed. + matches in a more rigorous manner. To the client, this has the effect + of emulating a Microsoft Domain. The client is not concerned whether + or not Samba looks up a Windows NT SAM or does it in some other way. + 44..22.. AAuutthheennttiiccaattiioonn SScchheemmeess + In the simple case authentication information is stored on a single server and the user types a password on connecting for the first time. However client operating systems often require a password before they @@ -661,7 +815,8 @@ different contexts just does not work. Some kind of distributed authentication database is needed. It must cope with password changes and provide for assigning groups of users the same level of access - permissions. + permissions. This is why Samba installations often choose to implement + a Domain model straight away. Authentication decisions are some of the biggest in designing a network. Are you going to use a scheme native to the client operating @@ -671,29 +826,49 @@ setups would be appreciated. refer to server FAQ for "passwd chat" passwd program password server etc etc... - 44..22..11.. WWoorrkkggrroouupp MMooddee SSeerrvviicceess - etc etc + 44..22..11.. NNIISS + + + For Windows 95, Windows for Workgroups and most other clients Samba + can be a domain controller and share the password database via NIS + transparently. Windows NT is different. Free NIS NT client + <http://www.dcs.qmw.ac.uk/~williams> + + + 44..22..22.. KKeerrbbeerrooss + + + Kerberos for US users only: Kerberos overview + <http://www.cygnus.com/product/unifying-security.html> Download + Kerberos <http://www.cygnus.com/product/kerbnet-download.html> + + + 44..22..33.. FFTTPP - 44..22..22.. WWiinnddoowwss NNTT--SSttyyllee DDoommaaiinn - Samba compiled with libdes - enabling encrypted passwords security = - server + Other NT w/s logon hack via NT - 44..22..33.. NNIISS - 44..22..44.. KKeerrbbeerrooss + 44..22..44.. DDeeffaauulltt SSeerrvveerr MMeetthhoodd - 44..22..55.. FFTTPP - 44..22..66.. DDeeffaauulltt SSeerrvveerr MMeetthhoodd - 44..22..77.. CClliieenntt--ssiiddee DDaattaabbaassee OOnnllyy + + + 44..22..55.. CClliieenntt--ssiiddee DDaattaabbaassee OOnnllyy + + 44..33.. PPoosstt--AAuutthheennttiiccaattiioonn:: NNeettllooggoonn,, LLooggoonn SSccrriippttss,, PPrrooffiilleess + + See <../DOMAIN.txt> + + 55.. CCrroossss--PPrroottooccooll FFiillee SShhaarriinngg + Samba is an important tool for... It is possible to... @@ -710,10 +885,40 @@ packages, Samba, and Linux (and other UNIX-based systems) see <http://www.eats.com/linux_mac_win.html> 3.5) Sniffing your nework + + 66.. MMiisscceellllaanneeoouuss + 66..11.. IIss SSaammbbaa YYeeaarr 22000000 ccoommpplliiaanntt?? + The CIFS protocol that Samba implements negotiates times in various formats, all of which are able to cope with dates beyond 2000. + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/faq/sambafaq-1.html b/docs/faq/sambafaq-1.html index 4b9e589e843..c010e50e011 100644 --- a/docs/faq/sambafaq-1.html +++ b/docs/faq/sambafaq-1.html @@ -197,7 +197,7 @@ There are a number of places to look for more information on Samba, including: <LI>Two mailing lists devoted to discussion of Samba-related matters. </LI> <LI>The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. </LI> <LI>The WWW site 'SAMBA Web Pages' at -<A HREF="http://samba.canberra.edu.au/pub/samba/samba.html">http://samba.canberra.edu.au/pub/samba/samba.html</A> includes: +<A HREF="http://samba.edu.au/samba/">http://samba.edu.au/samba/</A> includes: <UL> <LI>Links to man pages and documentation, including this FAQ</LI> <LI>A comprehensive survey of Samba users.</LI> diff --git a/docs/faq/sambafaq-3.html b/docs/faq/sambafaq-3.html index 8b24de54f23..1b5dcf4d9aa 100644 --- a/docs/faq/sambafaq-3.html +++ b/docs/faq/sambafaq-3.html @@ -76,7 +76,7 @@ To syncronize your PC's clock with your Samba server: <UL> <LI> Copy timesync.pif to your windows directory</LI> <LI> timesync.pif can be found at: -<A HREF="http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif">http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif</A></LI> +<A HREF="http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif">http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif</A></LI> <LI> Add timesync.pif to your 'Start Up' group/folder</LI> <LI> Open the properties dialog box for the program/icon</LI> <LI> Make sure the 'Run Minimized' option is set in program 'Properties'</LI> diff --git a/docs/faq/sambafaq.sgml b/docs/faq/sambafaq.sgml index 951ad822edb..d306881b56b 100644 --- a/docs/faq/sambafaq.sgml +++ b/docs/faq/sambafaq.sgml @@ -9,15 +9,17 @@ 9 June 1997 Paul Lots of changes, added doco list, updated compatible systems list added NT SP3 entry, added Year 2000 entry, Getting ready for 1.9.17 + v 0.8 7th Oct 97 Paul + changed samba.canberra entries to samba.anu.../samba/ --> <article> <title> Samba FAQ -<author>Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.7, June '97 +<date>v 0.8, June '97 <abstract> This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server @@ -191,7 +193,7 @@ There are a number of places to look for more information on Samba, including: <itemize> <item>Two mailing lists devoted to discussion of Samba-related matters. <item>The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. -<item>The WWW site 'SAMBA Web Pages' at <url url="http://samba.canberra.edu.au/pub/samba/samba.html"> includes: +<item>The WWW site 'SAMBA Web Pages' at <url url="http://samba.edu.au/samba/"> includes: <itemize> <item>Links to man pages and documentation, including this FAQ <item>A comprehensive survey of Samba users. @@ -562,7 +564,8 @@ To syncronize your PC's clock with your Samba server: <itemize> <item> Copy timesync.pif to your windows directory <item> timesync.pif can be found at: - <url url="http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif"> + <url +url="http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif"> <item> Add timesync.pif to your 'Start Up' group/folder <item> Open the properties dialog box for the program/icon <item> Make sure the 'Run Minimized' option is set in program 'Properties' diff --git a/docs/faq/sambafaq.txt b/docs/faq/sambafaq.txt index e7f5f32a20d..49cfa479fe9 100644 --- a/docs/faq/sambafaq.txt +++ b/docs/faq/sambafaq.txt @@ -92,7 +92,7 @@ 5.1. Is Samba Year 2000 compliant? ______________________________________________________________________ - 1. General Information + 11.. GGeenneerraall IInnffoorrmmaattiioonn @@ -101,7 +101,7 @@ details - 1.1. What is Samba? + 11..11.. WWhhaatt iiss SSaammbbaa?? Samba is a suite of programs which work together to allow clients to @@ -122,30 +122,30 @@ The components of the suite are (in summary): - o smbd, the SMB server. This handles actual connections from clients, + +o ssmmbbdd, the SMB server. This handles actual connections from clients, doing all the file, permission and username work - o nmbd, the Netbios name server, which helps clients locate servers, + +o nnmmbbdd, the Netbios name server, which helps clients locate servers, doing the browsing work and managing domains as this capability is being built into Samba - o smbclient, the Unix-hosted client program + +o ssmmbbcclliieenntt, the Unix-hosted client program - o smbrun, a little 'glue' program to help the server run external + +o ssmmbbrruunn, a little 'glue' program to help the server run external programs - o testprns, a program to test server access to printers + +o tteessttpprrnnss, a program to test server access to printers - o testparms, a program to test the Samba configuration file for + +o tteessttppaarrmmss, a program to test the Samba configuration file for correctness - o smb.conf, the Samba configuration file + +o ssmmbb..ccoonnff, the Samba configuration file - o smbprint, a sample script to allow a Unix host to use smbclient to + +o ssmmbbpprriinntt, a sample script to allow a Unix host to use smbclient to print to an SMB server - o Documentation! DON'T neglect to read it - you will save a great + +o DDooccuummeennttaattiioonn!! DON'T neglect to read it - you will save a great deal of time! The suite is supplied with full source (of course!) and is GPLed. @@ -155,7 +155,7 @@ and this FAQ were originally written by Karl Auer. - 1.2. What is the current version of Samba? + 11..22.. WWhhaatt iiss tthhee ccuurrrreenntt vveerrssiioonn ooff SSaammbbaa?? At time of writing, the current version was 1.9.17. If you want to be @@ -165,7 +165,7 @@ For more information see ``What do the version numbers mean?'' - 1.3. Where can I get it? + 11..33.. WWhheerree ccaann II ggeett iitt?? The Samba suite is available via anonymous ftp from samba.anu.edu.au. @@ -185,7 +185,7 @@ do contain Samba binaries for that platform. - 1.4. What do the version numbers mean? + 11..44.. WWhhaatt ddoo tthhee vveerrssiioonn nnuummbbeerrss mmeeaann?? It is not recommended that you run a version of Samba with the word @@ -234,7 +234,7 @@ sion. - 1.5. What platforms are supported? + 11..55.. WWhhaatt ppllaattffoorrmmss aarree ssuuppppoorrtteedd?? Many different platforms have run Samba successfully. The platforms @@ -242,188 +242,188 @@ At time of writing, the Makefile claimed support for: - o A/UX 3.0 + +o A/UX 3.0 - o AIX + +o AIX - o Altos Series 386/1000 + +o Altos Series 386/1000 - o Amiga + +o Amiga - o Apollo Domain/OS sr10.3 + +o Apollo Domain/OS sr10.3 - o BSDI + +o BSDI - o B.O.S. (Bull Operating System) + +o B.O.S. (Bull Operating System) - o Cray, Unicos 8.0 + +o Cray, Unicos 8.0 - o Convex + +o Convex - o DGUX. + +o DGUX. - o DNIX. + +o DNIX. - o FreeBSD + +o FreeBSD - o HP-UX + +o HP-UX - o Intergraph. + +o Intergraph. - o Linux with/without shadow passwords and quota + +o Linux with/without shadow passwords and quota - o LYNX 2.3.0 + +o LYNX 2.3.0 - o MachTen (a unix like system for Macintoshes) + +o MachTen (a unix like system for Macintoshes) - o Motorola 88xxx/9xx range of machines + +o Motorola 88xxx/9xx range of machines - o NetBSD + +o NetBSD - o NEXTSTEP Release 2.X, 3.0 and greater (including OPENSTEP for + +o NEXTSTEP Release 2.X, 3.0 and greater (including OPENSTEP for Mach). - o OS/2 using EMX 0.9b + +o OS/2 using EMX 0.9b - o OSF1 + +o OSF1 - o QNX 4.22 + +o QNX 4.22 - o RiscIX. + +o RiscIX. - o RISCOs 5.0B + +o RISCOs 5.0B - o SEQUENT. + +o SEQUENT. - o SCO (including: 3.2v2, European dist., OpenServer 5) + +o SCO (including: 3.2v2, European dist., OpenServer 5) - o SGI. + +o SGI. - o SMP_DC.OSx v1.1-94c079 on Pyramid S series + +o SMP_DC.OSx v1.1-94c079 on Pyramid S series - o SONY NEWS, NEWS-OS (4.2.x and 6.1.x) + +o SONY NEWS, NEWS-OS (4.2.x and 6.1.x) - o SUNOS 4 + +o SUNOS 4 - o SUNOS 5.2, 5.3, and 5.4 (Solaris 2.2, 2.3, and '2.4 and later') + +o SUNOS 5.2, 5.3, and 5.4 (Solaris 2.2, 2.3, and '2.4 and later') - o Sunsoft ISC SVR3V4 + +o Sunsoft ISC SVR3V4 - o SVR4 + +o SVR4 - o System V with some berkely extensions (Motorola 88k R32V3.2). + +o System V with some berkely extensions (Motorola 88k R32V3.2). - o ULTRIX. + +o ULTRIX. - o UNIXWARE + +o UNIXWARE - o UXP/DS + +o UXP/DS - 1.6. How can I find out more about Samba? + 11..66.. HHooww ccaann II ffiinndd oouutt mmoorree aabboouutt SSaammbbaa?? There are a number of places to look for more information on Samba, including: - o Two mailing lists devoted to discussion of Samba-related matters. + +o Two mailing lists devoted to discussion of Samba-related matters. - o The newsgroup, comp.protocols.smb, which has a great deal of + +o The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. - o The WWW site 'SAMBA Web Pages' at - <http://samba.canberra.edu.au/pub/samba/samba.html> includes: + +o The WWW site 'SAMBA Web Pages' at <http://samba.edu.au/samba/> + includes: - o Links to man pages and documentation, including this FAQ + +o Links to man pages and documentation, including this FAQ - o A comprehensive survey of Samba users. + +o A comprehensive survey of Samba users. - o A searchable hypertext archive of the Samba mailing list. + +o A searchable hypertext archive of the Samba mailing list. - o Links to Samba source code, binaries, and mirrors of both. + +o Links to Samba source code, binaries, and mirrors of both. - o The long list of topic documentation. These files can be found in + +o The long list of topic documentation. These files can be found in the 'docs' directory of the Samba source, or at <ftp://samba.anu.edu.au/pub/samba/docs/> - o Application_Serving.txt + +o Application_Serving.txt <ftp://samba.anu.edu.au/pub/samba/docs/Application_Serving.txt> - o BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt> + +o BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt> - o BUGS.txt <ftp://samba.anu.edu.au/pub/samba/docs/BUGS.txt> + +o BUGS.txt <ftp://samba.anu.edu.au/pub/samba/docs/BUGS.txt> - o DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/docs/DIAGNOSIS.txt> + +o DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/docs/DIAGNOSIS.txt> - o DNIX.txt <ftp://samba.anu.edu.au/pub/samba/docs/DNIX.txt> + +o DNIX.txt <ftp://samba.anu.edu.au/pub/samba/docs/DNIX.txt> - o DOMAIN.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN.txt> + +o DOMAIN.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN.txt> - o CONTROL.txt + +o CONTROL.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN_CONTROL.txt> - o ENCRYPTION.txt + +o ENCRYPTION.txt <ftp://samba.anu.edu.au/pub/samba/docs/ENCRYPTION.txt> - o Faxing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Faxing.txt> + +o Faxing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Faxing.txt> - o GOTCHAS.txt <ftp://samba.anu.edu.au/pub/samba/docs/GOTCHAS.txt> + +o GOTCHAS.txt <ftp://samba.anu.edu.au/pub/samba/docs/GOTCHAS.txt> - o HINTS.txt <ftp://samba.anu.edu.au/pub/samba/docs/HINTS.txt> + +o HINTS.txt <ftp://samba.anu.edu.au/pub/samba/docs/HINTS.txt> - o INSTALL.sambatar + +o INSTALL.sambatar <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.sambatar> - o INSTALL.txt <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.txt> + +o INSTALL.txt <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.txt> - o MIRRORS <ftp://samba.anu.edu.au/pub/samba/docs/MIRRORS> + +o MIRRORS <ftp://samba.anu.edu.au/pub/samba/docs/MIRRORS> - o NetBIOS.txt <ftp://samba.anu.edu.au/pub/samba/docs/NetBIOS.txt> + +o NetBIOS.txt <ftp://samba.anu.edu.au/pub/samba/docs/NetBIOS.txt> - o OS2.txt <ftp://samba.anu.edu.au/pub/samba/docs/OS2.txt> + +o OS2.txt <ftp://samba.anu.edu.au/pub/samba/docs/OS2.txt> - o PROJECTS <ftp://samba.anu.edu.au/pub/samba/docs/PROJECTS> + +o PROJECTS <ftp://samba.anu.edu.au/pub/samba/docs/PROJECTS> - o Passwords.txt <ftp://samba.anu.edu.au/pub/samba/docs/Passwords.txt> + +o Passwords.txt <ftp://samba.anu.edu.au/pub/samba/docs/Passwords.txt> - o Printing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Printing.txt> + +o Printing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Printing.txt> - o README.DCEDFS <ftp://samba.anu.edu.au/pub/samba/docs/README.DCEDFS> + +o README.DCEDFS <ftp://samba.anu.edu.au/pub/samba/docs/README.DCEDFS> - o README.OS2 <ftp://samba.anu.edu.au/pub/samba/docs/README.OS2> + +o README.OS2 <ftp://samba.anu.edu.au/pub/samba/docs/README.OS2> - o README.jis <ftp://samba.anu.edu.au/pub/samba/docs/README.jis> + +o README.jis <ftp://samba.anu.edu.au/pub/samba/docs/README.jis> - o README.sambatar + +o README.sambatar <ftp://samba.anu.edu.au/pub/samba/docs/README.sambatar> - o SCO.txt <ftp://samba.anu.edu.au/pub/samba/docs/SCO.txt> + +o SCO.txt <ftp://samba.anu.edu.au/pub/samba/docs/SCO.txt> - o SMBTAR.notes <ftp://samba.anu.edu.au/pub/samba/docs/SMBTAR.notes> + +o SMBTAR.notes <ftp://samba.anu.edu.au/pub/samba/docs/SMBTAR.notes> - o Speed.txt <ftp://samba.anu.edu.au/pub/samba/docs/Speed.txt> + +o Speed.txt <ftp://samba.anu.edu.au/pub/samba/docs/Speed.txt> - o Support.txt <ftp://samba.anu.edu.au/pub/samba/docs/Support.txt> + +o Support.txt <ftp://samba.anu.edu.au/pub/samba/docs/Support.txt> - o THANKS <ftp://samba.anu.edu.au/pub/samba/docs/THANKS> + +o THANKS <ftp://samba.anu.edu.au/pub/samba/docs/THANKS> - o Tracing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Tracing.txt> + +o Tracing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Tracing.txt> - o SMB.txt <ftp://samba.anu.edu.au/pub/samba/docs/UNIX-SMB.txt> + +o SMB.txt <ftp://samba.anu.edu.au/pub/samba/docs/UNIX-SMB.txt> - o Warp.txt <ftp://samba.anu.edu.au/pub/samba/docs/Warp.txt> + +o Warp.txt <ftp://samba.anu.edu.au/pub/samba/docs/Warp.txt> - o WinNT.txt <ftp://samba.anu.edu.au/pub/samba/docs/WinNT.txt> + +o WinNT.txt <ftp://samba.anu.edu.au/pub/samba/docs/WinNT.txt> - o history <ftp://samba.anu.edu.au/pub/samba/docs/history> + +o history <ftp://samba.anu.edu.au/pub/samba/docs/history> - o level.txt + +o level.txt <ftp://samba.anu.edu.au/pub/samba/docs/security_level.txt> - o slip.htm <ftp://samba.anu.edu.au/pub/samba/docs/wfw_slip.htm> + +o slip.htm <ftp://samba.anu.edu.au/pub/samba/docs/wfw_slip.htm> - 1.7. How do I subscribe to the Samba Mailing Lists? + 11..77.. HHooww ddoo II ssuubbssccrriibbee ttoo tthhee SSaammbbaa MMaaiilliinngg LLiissttss?? Send email to listproc@samba.anu.edu.au. Make sure the subject line is @@ -456,14 +456,14 @@ - The From: line in your message MUST be the same address you used when + The FFrroomm:: line in your message _M_U_S_T be the same address you used when you subscribed. - 1.8. Something's gone wrong - what should I do? + 11..88.. SSoommeetthhiinngg''ss ggoonnee wwrroonngg -- wwhhaatt sshhoouulldd II ddoo?? - # *** IMPORTANT! *** # + ## ****** IIMMPPOORRTTAANNTT!! ****** ## DO NOT post messages on mailing lists or in newsgroups until you have carried out the first three steps given here! @@ -501,7 +501,7 @@ Tridgell or any other individual, they may be lost if you do. - 1.9. Pizza supply details + 11..99.. PPiizzzzaa ssuuppppllyy ddeettaaiillss Those who have registered in the Samba survey as "Pizza Factory" will @@ -531,11 +531,11 @@ hungry sniffer dogs but it will have been a noble gesture. - 2. Compiling and installing Samba on a Unix host + 22.. CCoommppiilliinngg aanndd iinnssttaalllliinngg SSaammbbaa oonn aa UUnniixx hhoosstt - 2.1. I can't see the Samba server in any browse lists! + 22..11.. II ccaann''tt sseeee tthhee SSaammbbaa sseerrvveerr iinn aannyy bbrroowwssee lliissttss!! See BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/BROWSING.txt> for @@ -557,14 +557,14 @@ client to client - check your client's documentation. - 2.2. Some files that I KNOW are on the server doesn't show up when I - view the files from my client! + 22..22.. SSoommee ffiilleess tthhaatt II KKNNOOWW aarree oonn tthhee sseerrvveerr ddooeessnn''tt sshhooww uupp wwhheenn II + vviieeww tthhee ffiilleess ffrroomm mmyy cclliieenntt!! See the next question. - 2.3. Some files on the server show up with really wierd filenames - when I view the files from my client! + 22..33.. SSoommee ffiilleess oonn tthhee sseerrvveerr sshhooww uupp wwiitthh rreeaallllyy wwiieerrdd ffiilleennaammeess + wwhheenn II vviieeww tthhee ffiilleess ffrroomm mmyy cclliieenntt!! If you check what files are not showing up, you will note that they @@ -579,7 +579,7 @@ "mangled names = yes". - 2.4. My client reports "cannot locate specified computer" or similar + 22..44.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott llooccaattee ssppeecciiffiieedd ccoommppuutteerr"" oorr ssiimmiillaarr This indicates one of three things: You supplied an incorrect server @@ -610,8 +610,8 @@ tests :-) - 2.5. My client reports "cannot locate specified share name" or simi- - lar + 22..55.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott llooccaattee ssppeecciiffiieedd sshhaarree nnaammee"" oorr ssiimmii-- + llaarr This message indicates that your client CAN locate the specified @@ -624,19 +624,19 @@ to specify a service name correctly), read on: - o Many clients cannot accept or use service names longer than eight + +o Many clients cannot accept or use service names longer than eight characters. - o Many clients cannot accept or use service names containing spaces. + +o Many clients cannot accept or use service names containing spaces. - o Some servers (not Samba though) are case sensitive with service + +o Some servers (not Samba though) are case sensitive with service names. - o Some clients force service names into upper case. + +o Some clients force service names into upper case. - 2.6. My client reports "cannot find domain controller", "cannot log - on to the network" or similar + 22..66.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott ffiinndd ddoommaaiinn ccoonnttrroolllleerr"",, ""ccaannnnoott lloogg + oonn ttoo tthhee nneettwwoorrkk"" oorr ssiimmiillaarr Nothing is wrong - Samba does not implement the primary domain name @@ -658,7 +658,7 @@ - 2.7. Printing doesn't work :-( + 22..77.. PPrriinnttiinngg ddooeessnn''tt wwoorrkk ::--(( Make sure that the specified print command for the service you are @@ -689,8 +689,8 @@ mechanism. - 2.8. My programs install on the server OK, but refuse to work prop- - erly + 22..88.. MMyy pprrooggrraammss iinnssttaallll oonn tthhee sseerrvveerr OOKK,, bbuutt rreeffuussee ttoo wwoorrkk pprroopp-- + eerrllyy There are numerous possible reasons for this, but one MAJOR @@ -706,7 +706,7 @@ Tridgell know via email at samba-bugs@samba.anu.edu.au. - 2.9. My "server string" doesn't seem to be recognised + 22..99.. MMyy ""sseerrvveerr ssttrriinngg"" ddooeessnn''tt sseeeemm ttoo bbee rreeccooggnniisseedd OR My client reports the default setting, eg. "Samba 1.9.15p4", @@ -719,8 +719,8 @@ the "server string" field of smb.conf, -C for nmbd is now obsolete. - 2.10. My client reports "This server is not configured to list shared - resources" + 22..1100.. MMyy cclliieenntt rreeppoorrttss ""TThhiiss sseerrvveerr iiss nnoott ccoonnffiigguurreedd ttoo lliisstt sshhaarreedd + rreessoouurrcceess"" Your guest account is probably invalid for some reason. Samba uses the @@ -730,7 +730,7 @@ See also 'guest account' in smb.conf man page. - 2.11. Log message "you appear to have a trapdoor uid system" + 22..1111.. LLoogg mmeessssaaggee ""yyoouu aappppeeaarr ttoo hhaavvee aa ttrraappddoooorr uuiidd ssyysstteemm"" This can have several causes. It might be because you are using a uid @@ -765,12 +765,12 @@ as uid 65535 will actually run as root. This is not good! - 3. Common client questions + 33.. CCoommmmoonn cclliieenntt qquueessttiioonnss - 3.1. Are there any Macintosh clients for Samba? + 33..11.. AArree tthheerree aannyy MMaacciinnttoosshh cclliieennttss ffoorr SSaammbbaa?? Yes! Thursby now have a CIFS Client / Server called DAVE - see @@ -790,7 +790,7 @@ Windows users, these packages offer to Macs. For more info on these packages, Samba, and Linux (and other UNIX-based systems) see <http://www.eats.com/linux_mac_win.html> - 3.2. Session request failed (131,130)" error + 33..22.. SSeessssiioonn rreeqquueesstt ffaaiilleedd ((113311,,113300))"" eerrrroorr The following answer is provided by John E. Miller: @@ -819,26 +819,26 @@ you'd have to use smbclient -iSomeStr otherparms in connecting to it. - 3.3. How do I synchronise my PC's clock with my Samba server? + 33..33.. HHooww ddoo II ssyynncchhrroonniissee mmyy PPCC''ss cclloocckk wwiitthh mmyy SSaammbbaa sseerrvveerr?? To syncronize your PC's clock with your Samba server: - o Copy timesync.pif to your windows directory + +o Copy timesync.pif to your windows directory - o timesync.pif can be found at: - <http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif> + +o timesync.pif can be found at: + <http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif> - o Add timesync.pif to your 'Start Up' group/folder + +o Add timesync.pif to your 'Start Up' group/folder - o Open the properties dialog box for the program/icon + +o Open the properties dialog box for the program/icon - o Make sure the 'Run Minimized' option is set in program 'Properties' + +o Make sure the 'Run Minimized' option is set in program 'Properties' - o Change the command line section that reads \sambahost to reflect + +o Change the command line section that reads \sambahost to reflect the name of your server. - o Close the properties dialog box by choosing 'OK' + +o Close the properties dialog box by choosing 'OK' Each time you start your computer (or login for Win95) your PC will synchronize its clock with your Samba server. @@ -858,7 +858,7 @@ as one of the lines in the logon script. - 3.4. Problems with WinDD, NTrigue, WinCenterPro etc + 33..44.. PPrroobblleemmss wwiitthh WWiinnDDDD,, NNTTrriigguuee,, WWiinnCCeenntteerrPPrroo eettcc All of the above programs are applications that sit on an NT box and @@ -900,7 +900,7 @@ home directory. Use \serversername instead. - 3.5. Problem with printers under NT + 33..55.. PPrroobblleemm wwiitthh pprriinntteerrss uunnddeerr NNTT This info from Stefan Hergeth hergeth@f7axp1.informatik.fh-muenchen.de @@ -929,7 +929,7 @@ try it yet. - 3.6. Why are my file's timestamps off by an hour, or by a few hours? + 33..66.. WWhhyy aarree mmyy ffiillee''ss ttiimmeessttaammppss ooffff bbyy aann hhoouurr,, oorr bbyy aa ffeeww hhoouurrss?? This is from Paul Eggert eggert@twinsun.com. @@ -973,20 +973,20 @@ where: - o `Std' is the standard time designation (e.g. `PST'). + +o `Std' is the standard time designation (e.g. `PST'). - o `Offset' is the number of hours behind UTC (e.g. `8'). Prepend + +o `Offset' is the number of hours behind UTC (e.g. `8'). Prepend a `-' if you are ahead of UTC, and append `:30' if you are at a half-hour offset. Omit all the remaining items if you do not use daylight-saving time. - o `Dst' is the daylight-saving time designation (e.g. `PDT'). + +o `Dst' is the daylight-saving time designation (e.g. `PDT'). The optional second `Offset' is the number of hours that daylight-saving time is behind UTC. The default is 1 hour ahead of standard time. - o `Date/Time,Date/Time' specify when daylight-saving time starts + +o `Date/Time,Date/Time' specify when daylight-saving time starts and ends. The format for a date is `Mm.n.d', which specifies the dth day (0 is Sunday) of the nth week of the mth month, where week 5 means the last such day in the month. The format @@ -1005,7 +1005,7 @@ Samba server to 1.9.16alpha10 or later. - 3.7. How do I set the printer driver name correctly? + 33..77.. HHooww ddoo II sseett tthhee pprriinntteerr ddrriivveerr nnaammee ccoorrrreeccttllyy?? Question: On NT, I opened "Printer Manager" and "Connect to Printer". @@ -1050,17 +1050,17 @@ this is effectively what older versions of Samba did, so if that worked for you then give it a go. If this does work then let us know - via samba-bugs@samba.anu.edu.au, and we'll make it the default. Currently - the default is a 0 length string. + via samba-bugs@samba.anu.edu.au, and we'll make it the default. Cur- + rently the default is a 0 length string. - 3.8. I've applied NT 4.0 SP3, and now I can't access Samba shares, - Why? + 33..88.. II''vvee aapppplliieedd NNTT 44..00 SSPP33,, aanndd nnooww II ccaann''tt aacccceessss SSaammbbaa sshhaarreess,, + WWhhyy?? As of SP3, Microsoft has decided that they will no longer default to passing clear text passwords over the network. To enable access to - Samba shares from NT 4.0 SP3, you must do ONE of two things: + Samba shares from NT 4.0 SP3, you must do OONNEE of two things: 1. Set the Samba configuration option 'security = user' and implement all of the stuff detailed in ENCRYPTION.txt @@ -1071,13 +1071,13 @@ <http://www.microsoft.com/kb/articles/q166/7/30.htm> - 4. Specific client application problems + 44.. SSppeecciiffiicc cclliieenntt aapppplliiccaattiioonn pprroobblleemmss - 4.1. MS Office Setup reports "Cannot change properties of 'MSOF- - FICEUP.INI'" + 44..11.. MMSS OOffffiiccee SSeettuupp rreeppoorrttss ""CCaannnnoott cchhaannggee pprrooppeerrttiieess ooff ''MMSSOOFF-- + FFIICCEEUUPP..IINNII''"" When installing MS Office on a Samba drive for which you have admin @@ -1093,11 +1093,11 @@ to fix the owner. - 5. Miscellaneous + 55.. MMiisscceellllaanneeoouuss - 5.1. Is Samba Year 2000 compliant? + 55..11.. IIss SSaammbbaa YYeeaarr 22000000 ccoommpplliiaanntt?? The CIFS protocol that Samba implements negotiates times in various diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7 index 7e98c850d41..7260cbad396 100644 --- a/docs/manpages/samba.7 +++ b/docs/manpages/samba.7 @@ -65,7 +65,7 @@ the mailing list are given in the README file that comes with Samba. If you have access to a WWW viewer (such as Netscape or Mosaic) then you will also find lots of useful information, including back issues -of the Samba mailing list, at http://samba.canberra.edu.au/pub/samba/ +of the Samba mailing list, at http://samba.anu.edu.au/samba/ .SH AUTHOR The main author of the Samba suite is Andrew Tridgell. He may be diff --git a/docs/samba.faq b/docs/samba.faq deleted file mode 100644 index 19126439500..00000000000 --- a/docs/samba.faq +++ /dev/null @@ -1,900 +0,0 @@ - - Frequently Asked Questions - - about the - - SAMBA Suite - - (FAQ version 1.9.15a, Samba version 1.09.15) - -------------------------------------------------------------------------------- - -This FAQ was originally prepared by Karl Auer and is -currently maintained by Paul Blackman (ictinus@lake.canberra.edu.au). - -As Karl originally said, 'this FAQ was prepared with lots of help from numerous -net.helpers', and that's the way I'd like to keep it. So if you find anything -that you think should be in here don't hesitate to contact me. - -Thanks to Karl for the work he's done, and continuing thanks to Andrew Tridgell -for developing Samba. - -Note: This FAQ is (and probably always will be) under construction. Some -sections exist only as optimistic entries in the Contents page. - -------------------------------------------------------------------------------- - -Contents - - * SECTION ONE: General information - All about Samba - what it is, how to get it, related sources of - information, how to understand the version numbering scheme, - pizza details - * SECTION TWO: Compiling and installing Samba on a Unix host - Common problems that arise when building and installing Samba under - Unix. - * SECTION THREE: Common client problems - Common problems that arise when trying to communicate from a client - computer to a Samba server. All problems which have symptoms you see - at the client end will be in this section. - * SECTION FOUR: Specific client problems - This section covers problems that are specific to certain clients, - such as Windows for Workgroups or Windows NT. Please check Section - Three first! - * SECTION FIVE: Specific client application problems - This section covers problems that are specific to certain products, - such as Windows for Workgroups or Windows NT. Please check Sections - Three and Four first! - * SECTION SIX: Miscellaneous - All the questions that aren't classifiable into any other section. - - -=============================================================================== -SECTION ONE: General information -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: What is Samba? - -Samba is a suite of programs which work together to allow clients to access -to a server's filespace and printers via the SMB (Session Message Block) -protocol. Initially written for Unix, Samba now also runs on Netware, OS/2 and -AmigaDOS. - -In practice, this means that you can redirect disks and printers to Unix disks -and printers from Lan Manager clients, Windows for Workgroups 3.11 clients, -Windows NT clients, Linux clients and OS/2 clients. There is also a generic -Unix client program supplied as part of the suite which allows Unix users to -use an ftp-like interface to access filespace and printers on any other SMB -servers. This gives the capability for these operating systems to behave much -like a LAN Server or Windows NT Server machine, only with added functionality -and flexibility designed to make life easier for administrators. - -The components of the suite are (in summary): - - * smbd, the SMB server. This handles actual connections from clients, - doing all the file, permission and username work - * nmbd, the Netbios name server, which helps clients locate servers, - doing the browsing work and managing domains as this capability is - being built into Samba - * smbclient, the Unix-hosted client program - * smbrun, a little 'glue' program to help the server run external - programs - * testprns, a program to test server access to printers - * testparms, a program to test the Samba configuration file for - correctness - * smb.conf, the Samba configuration file - * smbprint, a sample script to allow a Unix host to use smbclient to - print to an SMB server - * documentation! DON'T neglect to read it - you will save a great deal - of time! - -The suite is supplied with full source (of course!) and is GPLed. - -The primary creator of the Samba suite is Andrew Tridgell. Later versions -incorporate much effort by many net.helpers. The man pages and this FAQ were -originally written by Karl Auer. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: What is the current version of Samba? - -At time of writing, the current version was 1.9.16. If you want to be sure -check the bottom of the change-log file. -(ftp://samba.anu.edu.au/pub/samba/alpha/change-log) - -For more information see question 5, "What do the version numbers mean?" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: Where can I get it? - -The Samba suite is available via anonymous ftp from samba.anu.edu.au. The -latest and greatest versions of the suite are in the directory: - -/pub/samba/ - -Development (read "alpha") versions, which are NOT necessarily stable and which -do NOT necessarily have accurate documentation, are available in the directory: - -/pub/samba/alpha - -Note that binaries are NOT included in any of the above. Samba is distributed -ONLY in source form, though binaries may be available from other sites. Recent -versions of some Linux distributions, for example, do contain Samba binaries -for that platform. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: What do the version numbers mean? - -It is not recommended that you run a version of Samba with the word "alpha" -in its name unless you know what you are doing and are willing to do some -debugging. Many, many people just get the latest recommended stable release -version and are happy. If you are brave, by all means take the plunge and -help with the testing and development - but don't install it on your -departmental server. Samba is typically very stable and safe, and this is -mostly due to the policy of many public releases. - -How the scheme works: - -1) when major changes are made the version number is increased. For example, -the transition from 1.9.15 to 1.9.16. However, this version number will not -appear immediately and people should continue to use 1.9.15 for production -systems (see next point.) - -2) just after major changes are made the software is considered -unstable, and a series of alpha releases are distributed, for example -1.9.16alpha1. These are for testing by those who know what they are doing. -The "alpha" in the filename will hopefully scare off those who are just -looking for the latest version to install. - -3) when Andrew thinks that the alphas have stabilised to the point where he -would recommend new users install it, he renames it to the same version -number without the alpha, for example 1.9.16. - -4) inevitably bugs are found in the "stable" releases and minor -patch levels are released which give us the pXX series, for example -1.9.16p2. - -So the progression goes: - - 1.9.15p7 (production) - 1.9.15p8 (production) - 1.9.16alpha1 (test sites only) - : - 1.9.16alpha20 (test sites only) - 1.9.16 (production) - 1.9.16p1 (production) - -The above system means that whenever someone looks at the samba ftp site -they will be able to grab the highest numbered release without an -alpha in the name and be sure of getting the current recommended -version. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: What platforms are supported? - -Many different platforms have run Samba successfully. The platforms most widely -used and thus best tested are Linux and SunOS. - -At time of writing, the Makefile claimed support for: - - * SunOS - * Linux with shadow passwords - * Linux without shadow passwords - * SOLARIS - * SOLARIS 2.2 and above (aka SunOS 5) - * SVR4 - * ULTRIX - * OSF1 (alpha only) - * OSF1 with NIS and Fast Crypt (alpha only) - * OSF1 V2.0 Enhanced Security (alpha only) - * AIX - * BSDI - * NetBSD - * NetBSD 1.0 - * SEQUENT - * HP-UX - * SGI - * SGI IRIX 4.x.x - * SGI IRIX 5.x.x - * FreeBSD - * NeXT 3.2 and above - * NeXT OS 2.x - * NeXT OS 3.0 - * ISC SVR3V4 (POSIX mode) - * ISC SVR3V4 (iBCS2 mode) - * A/UX 3.0 - * SCO with shadow passwords. - * SCO with shadow passwords, without YP. - * SCO with TCB passwords - * SCO 3.2v2 (ODT 1.1) with TCP passwords - * intergraph - * DGUX - * Apollo Domain/OS sr10.3 (BSD4.3) - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: How can I find out more about Samba? - -There are two mailing lists devoted to discussion of Samba-related matters. -There is also the newsgroup, comp.protocols.smb, which has a great deal of -discussion on Samba. There is also a WWW site 'SAMBA Web Pages' at -http://samba.canberra.edu.au/pub/samba/samba.html, under which there is a -comprehensive survey of Samba users. Another useful resource is the hypertext -archive of the Samba mailing list. - -Send email to listproc@samba.anu.edu.au. Make sure the subject line is -blank, and include the following two lines in the body of the message: - - subscribe samba Firstname Lastname - subscribe samba-announce Firstname Lastname - -Obviously you should substitute YOUR first name for "Firstname" and YOUR last -name for "Lastname"! Try not to send any signature stuff, it sometimes confuses -the list processor. - -The samba list is a digest list - every eight hours or so it regurgitates a -single message containing all the messages that have been received by the list -since the last time and sends a copy of this message to all subscribers. - -If you stop being interested in Samba, please send another email to -listproc@samba.anu.edu.au. Make sure the subject line is blank, and -include the following two lines in the body of the message: - - unsubscribe samba - unsubscribe samba-announce - -The From: line in your message MUST be the same address you used when you -subscribed. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: Something's gone wrong - what should I do? - -[#] *** IMPORTANT! *** [#] -DO NOT post messages on mailing lists or in newsgroups until you have carried -out the first three steps given here! - -Firstly, see if there are any likely looking entries in this FAQ! If you have -just installed Samba, have you run through the checklist in DIAGNOSIS.txt? It -can save you a lot of time and effort. - -Secondly, read the man pages for smbd, nmbd and smb.conf, looking for topics -that relate to what you are trying to do. - -Thirdly, if there is no obvious solution to hand, try to get a look at the log -files for smbd and/or nmbd for the period during which you were having -problems. You may need to reconfigure the servers to provide more extensive -debugging information - usually level 2 or level 3 provide ample debugging -info. Inspect these logs closely, looking particularly for the string "Error:". - -Fourthly, if you still haven't got anywhere, ask the mailing list or newsgroup. -In general nobody minds answering questions provided you have followed the -preceding steps. It might be a good idea to scan the archives of the mailing -list, which are available through the Samba web site described in the previous -section. - -If you successfully solve a problem, please mail the FAQ maintainer a succinct -description of the symptom, the problem and the solution, so I can incorporate -it in the next version. - -If you make changes to the source code, _please_ submit these patches so that -everyone else gets the benefit of your work. This is one of the most important -aspects to the maintainence of Samba. Send all patches to -samba-bugs@samba.anu.edu.au, not Andrew Tridgell or any other individual and -not the samba team mailing list. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* n: Pizza Supply Details - -Those who have registered in the Samba survey as "Pizza Factory" will already -know this, but the rest may need some help. Andrew doesn't ask for payment, -but he does appreciate it when people give him pizza. This calls for a little -organisation when the pizza donor is twenty thousand kilometres away, but -it has been done. - -Method 1: Ring up your local branch of an international pizza chain and see if -they honour their vouchers internationally. Pizza Hut do, which is how the -entire Canberra Linux Users Group got to eat pizza one night, courtesy of -someone in the US - -Method 2: Ring up a local pizza shop in Canberra and quote a credit card -number for a certain amount, and tell them that Andrew will be collecting -it (don't forget to tell him.) One kind soul from Germany did this. - -Method 3: Purchase a pizza voucher from your local pizza shop that has no -international affiliations and send it to Andrew. It is completely useless -but he can hang it on the wall next to the one he already has from Germany :-) - -Method 4: Air freight him a pizza with your favourite regional flavours. It will -probably get stuck in customs or torn apart by hungry sniffer dogs but it will -have been a noble gesture. - -=============================================================================== -SECTION TWO: Compiling and installing Samba on a Unix host -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -=============================================================================== -SECTION THREE: Common client problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: I can't see the Samba server in any browse lists! - -*** Until the FAQ can be updated, please check the file: -*** ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt -*** for more information on browsing. - -If your GUI client does not permit you to select non-browsable servers, you may -need to do so on the command line. For example, under Lan Manager you might -connect to the above service as disk drive M: thusly: - - net use M: \\mary\fred - -The details of how to do this and the specific syntax varies from client to -client - check your client's documentation. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: Some files that I KNOW are on the server doesn't show up when I view the - directories from my client! - -If you check what files are not showing up, you will note that they are files -which contain upper case letters or which are otherwise not DOS-compatible (ie, -they are not legal DOS filenames for some reason). - -The Samba server can be configured either to ignore such files completely, or -to present them to the client in "mangled" form. If you are not seeing the -files at all, the Samba server has most likely been configured to ignore them. -Consult the man page smb.conf(5) for details of how to change this - the -parameter you need to set is "mangled names = yes". - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: Some files on the server show up with really wierd filenames when I view -the directories from my client! - -If you check what files are showing up wierd, you will note that they are files -which contain upper case letters or which are otherwise not DOS-compatible (ie, -they are not legal DOS filenames for some reason). - -The Samba server can be configured either to ignore such files completely, or -to present them to the client in "mangled" form. If you are seeing strange file -names, they are most likely "mangled". If you would prefer to have such files -ignored rather than presented in "mangled" form, consult the man page -smb.conf(5) for details of how to change the server configuration - the -parameter you need to set is "mangled names = no". - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: My client reports "cannot locate specified computer" or similar. - -This indicates one of three things: You supplied an incorrect server name, the -underlying TCP/IP layer is not working correctly, or the name you specified -cannot be resolved. - -After carefully checking that the name you typed is the name you should have -typed, try doing things like pinging a host or telnetting to somewhere on your -network to see if TCP/IP is functioning OK. If it is, the problem is most -likely name resolution. - -If your client has a facility to do so, hardcode a mapping between the hosts IP -and the name you want to use. For example, with Man Manager or Windows for -Workgroups you would put a suitable entry in the file LMHOSTS. If this works, -the problem is in the communication between your client and the netbios name -server. If it does not work, then there is something fundamental wrong with -your naming and the solution is beyond the scope of this document. - -If you do not have any server on your subnet supplying netbios name resolution, -hardcoded mappings are your only option. If you DO have a netbios name server -running (such as the Samba suite's nmbd program), the problem probably lies in -the way it is set up. Refer to Section Two of this FAQ for more ideas. - -By the way, remember to REMOVE the hardcoded mapping before further tests :-) - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: My client reports "cannot locate specified share name" or similar. - -This message indicates that your client CAN locate the specified server, which -is a good start, but that it cannot find a service of the name you gave. - -The first step is to check the exact name of the service you are trying to -connect to (consult your system administrator). Assuming it exists and you -specified it correctly (read your client's doco on how to specify a service -name correctly), read on: - - * Many clients cannot accept or use service names longer than eight - characters. - * Many clients cannot accept or use service names containing spaces. - * Some servers (not Samba though) are case sensitive with service names. - * Some clients force service names into upper case. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: My client reports "cannot find domain controller", "cannot log on to the -network" or similar. - -Nothing is wrong - Samba does not implement the primary domain name controller -stuff for several reasons, including the fact that the whole concept of a -primary domain controller and "logging in to a network" doesn't fit well with -clients possibly running on multiuser machines (such as users of smbclient -under Unix). Having said that, several developers are working hard on -building it in to the next major version of Samba. If you can contribute, -send a message to samba-bugs! - -Seeing this message should not affect your ability to mount redirected disks -and printers, which is really what all this is about. - -For many clients (including Windows for Workgroups and Lan Manager), setting -the domain to STANDALONE at least gets rid of the message. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 7: Printing doesn't work :-( - -Make sure that the specified print command for the service you are connecting -to is correct and that it has a fully-qualified path (eg., use "/usr/bin/lpr" -rather than just "lpr"). - -Make sure that the spool directory specified for the service is writable by the -user connected to the service. In particular the user "nobody" often has -problems with printing, even if it worked with an earlier version of Samba. Try -creating another guest user other than "nobody". - -Make sure that the user specified in the service is permitted to use the -printer. - -Check the debug log produced by smbd. Search for the printer name and see if -the log turns up any clues. Note that error messages to do with a service ipc$ -are meaningless - they relate to the way the client attempts to retrieve status -information when using the LANMAN1 protocol. - -If using WfWg then you need to set the default protocol to TCP/IP, not Netbeui. -This is a WfWg bug. - -If using the Lanman1 protocol (the default) then try switching to coreplus. -Also not that print status error messages don't mean printing won't work. The -print status is received by a different mechanism. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 8: My programs install on the server OK, but refuse to work properly. - -There are numerous possible reasons for this, but one MAJOR possibility is that -your software uses locking. Make sure you are using Samba 1.6.11 or later. It -may also be possible to work around the problem by setting "locking=no" in the -Samba configuration file for the service the software is installed on. This -should be regarded as a strictly temporary solution. - -In earlier Samba versions there were some difficulties with the very latest -Microsoft products, particularly Excel 5 and Word for Windows 6. These should -have all been solved. If not then please let Andrew Tridgell know. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 9: My "server string" doesn't seem to be recognized, my client reports the - default setting, eg. "Samba 1.9.15p4", instead of what I have changed it - to in the smb.conf file. - -You need to use the -C option in nmbd. The "server string" affects -what smbd puts out and -C affects what nmbd puts out. In a future -version these will probably be combined and -C will be removed, but -for now use -C - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 10: When I attempt to get a listing of available resources from the Samba - server, my client reports - "This server is not configured to list shared resources". - -Your guest account is probably invalid for some reason. Samba uses -the guest account for browsing in smbd. Check that your guest account is -valid. - -See also 'guest account' in smb.conf man page. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 11: You get the message "you appear to have a trapdoor uid system" - in your logs - -This can have several causes. It might be because you are using a uid -or gid of 65535 or -1. This is a VERY bad idea, and is a big security -hole. Check carefully in your /etc/passwd file and make sure that no -user has uid 65535 or -1. Especially check the "nobody" user, as many -broken systems are shipped with nobody setup with a uid of 65535. - -It might also mean that your OS has a trapdoor uid/gid system :-) - -This means that once a process changes effective uid from root to -another user it can't go back to root. Unfortunately Samba relies on -being able to change effective uid from root to non-root and back -again to implement its security policy. If your OS has a trapdoor uid -system this won't work, and several things in Samba may break. Less -things will break if you use user or server level security instead of -the default share level security, but you may still strike -problems. - -The problems don't give rise to any security holes, so don't panic, -but it does mean some of Samba's capabilities will be unavailable. -In particular you will not be able to connect to the Samba server as -two different uids at once. This may happen if you try to print as a -"guest" while accessing a share as a normal user. It may also affect -your ability to list the available shares as this is normally done as -the guest user. - -Complain to your OS vendor and ask them to fix their system. - -Note: the reason why 65535 is a VERY bad choice of uid and gid is that -it casts to -1 as a uid, and the setreuid() system call ignores (with -no error) uid changes to -1. This means any daemon attempting to run -as uid 65535 will actually run as root. This is not good! - -=============================================================================== -SECTION FOUR: Specific client problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: Are any MacIntosh clients for Samba. - -Yes. Thursby Software Systems have released 'Dave' - a SMB client for -MacIntosh systems. This is a commercial product and inclusion in this -faq does not imply any endorsement by the Samba developers. Having said -that, the first public demonstration of 'Dave' was to the Samba server -run by Andrew Tridgell over the Internet from Redmond, Washington, USA to -Australia as part of the first CIFS developers conference. - -For more details on 'Dave' contact : - -Web contact: www.thursby.com - -Thursby Software Systems, Inc. -5840 W. Interstate 20 -Arlington, Texas 76017 U.S.A. -Voice: 817-478-5070 -FAX: 817-561-2313 -sales@thursby.com - -There are currently no Free Software solutions other than to make -your UNIX server talk AppleTalk. - -In Rob Newberry's words (rob@eats.com, Sun, 4 Dec 1994): - -In future Apple System Software, you may see support for other protocols, such -as SMB -- Applet is working on a new networking architecture that will make it -easier to support additional protocols. But it's not here yet. - -If you want your Unix machine to speak Appletalk, there are several options. -"Netatalk" and "CAP" are free, and available on the net. There are also -several commercial options, such as "PacerShare" and "Helios" (I think). -In any case, you'll have to look around for a server, not anything for the Mac. - -Depending on your OS, some of these may not help you. I am currently -coordinating the effort to get CAP working with Native Ethertalk under Linux, -but we're not done yet. - -Rob - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: I am getting a "Session request failed (131,130)" error when I try to - connect to my Win95 PC with smbclient. I am able to connect from the PC - to the Samba server without problems. What gives? - -The following answer is provided by John E. Miller: - -I'll assume that you're able to ping back and forth between the machines by -IP address and name, and that you're using some security model where you're -confident that you've got user IDs and passwords right. The logging options -(-d3 or greater) can help a lot with that. DNS and WINS configuration can -also impact connectivity as well. - -Now, on to 'scope id's. Somewhere in your Win95 TCP/IP network configuration -(I'm too much of an NT bigot to know where it's located in the Win95 setup, -but I'll have to learn someday since I teach for a Microsoft Solution Provider -Authorized Tech Education Center - what an acronym...) [Note: It's under -Control Panel | Network | TCP/IP | WINS Configuration] there's a little text -entry field called something like 'Scope ID'. - -This field essentially creates 'invisible' sub-workgroups on the same wire. -Boxes can only see other boxes whose Scope IDs are set to the exact same -value - it's sometimes used by OEMs to configure their boxes to browse only -other boxes from the same vendor and, in most environments, this field should -be left blank. If you, in fact, have something in this box that EXACT value -(case-sensitive!) needs to be provided to smbclient and nmbd as the -i -(lowercase) parameter. So, if your Scope ID is configured as the string -'SomeStr' in Win95 then you'd have to use smbclient -iSomeStr <otherparms> -in connecting to it. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: How do I synchronize my PC's clock with my Samba server? - -To syncronize your PC's clock with your Samba server: - -* Copy timesync.pif to your windows directory - * timesync.pif can be found at: - http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif -* Add timesync.pif to your 'Start Up' group/folder -* Open the properties dialog box for the program/icon - * Make sure the 'Run Minimized' option is set in program 'Properties' - * Change the command line section that reads \\sambahost to reflect the name - of your server. -* Close the properties dialog box by choosing 'OK' - -Each time you start your computer (or login for Win95) your PC will -synchronize its clock with your Samba server. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: Problems with WinDD, NTrigue, WinCenterPro etc - -All of the above programs are applications that sit on an NT box and -allow multiple users to access the NT GUI applications from remote -workstations (often over X). - -What has this got to do with Samba? The problem comes when these users -use filemanager to mount shares from a Samba server. The most common -symptom is that the first user to connect get correct file permissions -and has a nice day, but subsequent connections get logged in as the -same user as the first person to login. They find that they cannot -access files in their own home directory, but that they can access -files in the first users home directory (maybe not such a nice day -after all?) - -Why does this happen? The above products all share a common heritage -(and code base I believe). They all open just a single TCP based SMB -connection to the Samba server, and requests from all users are piped -over this connection. This is unfortunate, but not fatal. - -It means that if you run your Samba server in share level security -(the default) then things will definately break as described above. The -share level SMB security model has no provision for multiple user IDs -on the one SMB connection. See security_level.txt in the docs for more -info on share/user/server level security. - -If you run in user or server level security then you have a chance, -but only if you have a recent version of Samba (at least 1.9.15p6). In -older versions bugs in Samba meant you still would have had problems. - -If you have a trapdoor uid system in your OS then it will never work -properly. Samba needs to be able to switch uids on the connection and -it can't if your OS has a trapdoor uid system. You'll know this -because Samba will note it in your logs. - -Also note that you should not use the magic "homes" share name with -products like these, as otherwise all users will end up with the same -home directory. Use \\server\username instead. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: Problem with printers under NT - -This info from Stefan Hergeth may be useful: - - A network-printer (with ethernetcard) is connected to the NT-Clients via - our UNIX-Fileserver (SAMBA-Server), like the configuration told by - Matthew Harrell <harrell@leech.nrl.navy.mil> (see WinNT.txt) - - 1.) If a user has choosen this printer as the default printer in his - NT-Session and this printer is not connected to the network - (e.g. switched off) than this user has a problem with the SAMBA- - connection of his filesystems. It's very slow. - - 2.) If the printer is connected to the network everything works fine. - - 3.) When the smbd ist started with debug level 3, you can see that the - NT spooling system try to connect to the printer many times. If the - printer ist not connected to the network this request fails and the - NT spooler is wasting a lot of time to connect to the printer service. - This seems to be the reason for the slow network connection. - - 4.) Maybe it's possible to change this behaviour by setting different printer - properties in the Print-Manager-Menu of NT, but i didn't try it - yet. - - I hope this information will help in some way. - - Stefan Hergeth <hergeth@f7axp1.informatik.fh-muenchen.de> - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: Why are my file's timestamps off by an hour, or by a few hours? - -This is from Paul Eggert <eggert@twinsun.com>. - -Most likely it's a problem with your time zone settings. - -Internally, Samba maintains time in traditional Unix format, -namely, the number of seconds since 1970-01-01 00:00:00 Universal Time -(or ``GMT''), not counting leap seconds. - -On the server side, Samba uses the Unix TZ variable to convert internal -timestamps to and from local time. So on the server side, there are two -things to get right. - - 1. The Unix system clock must have the correct Universal time. - Use the shell command "sh -c 'TZ=UTC0 date'" to check this. - - 2. The TZ environment variable must be set on the server - before Samba is invoked. The details of this depend on the - server OS, but typically you must edit a file whose name is - /etc/TIMEZONE or /etc/default/init, or run the command `zic -l'. - - 3. TZ must have the correct value. - - 3a. If possible, use geographical time zone settings - (e.g. TZ='America/Los_Angeles' or perhaps - TZ=':US/Pacific'). These are supported by most - popular Unix OSes, are easier to get right, and are - more accurate for historical timestamps. If your - operating system has out-of-date tables, you should be - able to update them from the public domain time zone - tables at <URL:ftp://elsie.nci.nih.gov/pub/>. - - 3b. If your system does not support geographical time zone - settings, you must use a Posix-style TZ strings, e.g. - TZ='PST8PDT,M4.1.0/2,M10.5.0/2' for US Pacific time. - Posix TZ strings can take the following form (with optional - items in brackets): - - StdOffset[Dst[Offset],Date/Time,Date/Time] - - where: - - `Std' is the standard time designation (e.g. `PST'). - - `Offset' is the number of hours behind UTC (e.g. `8'). - Prepend a `-' if you are ahead of UTC, and - append `:30' if you are at a half-hour offset. - Omit all the remaining items if you do not use - daylight-saving time. - - `Dst' is the daylight-saving time designation - (e.g. `PDT'). - - The optional second `Offset' is the number of - hours that daylight-saving time is behind UTC. - The default is 1 hour ahead of standard time. - - `Date/Time,Date/Time' specify when daylight-saving - time starts and ends. The format for a date is - `Mm.n.d', which specifies the dth day (0 is Sunday) - of the nth week of the mth month, where week 5 means - the last such day in the month. The format for a - time is [h]h[:mm[:ss]], using a 24-hour clock. - - Other Posix string formats are allowed but you don't want - to know about them. - -On the client side, you must make sure that your client's clock and -time zone is also set appropriately. [[I don't know how to do this.]] - -Samba traditionally has had many problems dealing with time zones, due -to the bizarre ways that Microsoft network protocols handle time -zones. A common symptom is for file timestamps to be off by an hour. -To work around the problem, try disconnecting from your Samba server -and then reconnecting to it; or upgrade your Samba server to -1.9.16alpha10 or later. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 7: How do I set the printer driver name correctly? - -Question: -> On NT, I opened "Printer Manager" and "Connect to Printer". -> Enter "\\ptdi270\ps1" in the box of printer. I got the -> following error message: -> -> You do not have sufficient access to your machine -> to connect to the selected printer, since a driver -> needs to be installed locally. - -Answer: - -In the more recent versions of Samba you can now set the "printer -driver" in smb.conf. This tells the client what driver to use. For -example, I have: - - printer driver = HP LaserJet 4L - -and NT knows to use the right driver. You have to get this string -exactly right. - -To find the exact string to use, you need to get to the dialog box in -your client where you select which printer driver to install. The -correct strings for all the different printers are shown in a listbox -in that dialog box. - -You could also try setting the driver to NULL like this: - - printer driver = NULL - -this is effectively what older versions of Samba did, so if that -worked for you then give it a go. If this does work then let me know -and I'll make it the default. Currently the default is a 0 length -string. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* 8: I have upgraded my NT 4.0 system to service pack 3. Why - can't I connect anymore ? - -This is not a bug. Microsoft has changed their policy on sending -unencrypted passwords over the net. They no longer default to allowing -unencrypted passwords to be sent over the net. This effects all Samba -servers which are configured to use security=share or security=user level -security without password encryption. They do, however, have a fix which -can be applied to the registry to fix the problem. Here's a synopsis -from the SP3 web page that discusses how to enable unencrypted password -sending from an NT 4.0 box. - -A better solution is to re-compile Samba to use encrypted passwords. -See the document : - -ftp://samba.anu.edu.au/pub/samba/docs/ENCRYPTION.txt - ->SYMPTOMS ->========== -> ->Connecting to SMB servers (such as Samba) with unencrypted password fails -after upgrading to Windows NT 4.0 service pack 3 version 1.76. -> ->CAUSE ->====== -> ->The SMB redirector in Windows NT 4.0 service pack 3 version 1.76 handles ->unencrypted passwords differently than previous version of Windows NT. ->Beginning with this version, the SMB redirector will not send an ->unencrypted password unless you add a registry entry to enable them. -> ->RESOLUTION ->=========== -> ->To enable unencrypted (plain text) passwords modify the registry in this way. -> -> -> ->WARNING: Using Registry Editor incorrectly can cause serious, system-wide ->problems that may require you to reinstall Windows NT to correct them. ->Microsoft cannot guarantee that any problems resulting from the use of ->Registry Editor can be solved. Use this tool at your own risk. -> -> -> ->1. Run Registry Editor (REGEDT32.EXE). -> ->2. From the HKEY_LOCAL_MACHINE subtree, go to the following key: -> -> -> ->\system\currentcontrolset\services\rdr\parameters -> -> -> ->3. From the Edit menu, select Add Value. -> ->4. Add the following: -> -> -> ->Value Name: EnablePlainTextPassword -> ->Data Type: REG_DWORD -> ->Data: 1 -> -> -> ->5. Choose OK and quit Registry Editor. -> ->6. Shutdown and restart Windows NT. -> -> ------------------------------------------------------------------------ - -=============================================================================== -SECTION FIVE: Specific client application problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: MS Office Setup reports "Cannot change properties of the file named: - X:\MSOFFICE\SETUP.INI" - -When installing MS Office on a Samba drive for which you have admin user -permissions, ie. admin users = <username>, you will find the setup program -unable to complete the installation. - -To get around this problem, do the installation without admin user permissions -The problem is that MS Office Setup checks that a file is rdonly by trying to -open it for writing. - -Admin users can always open a file for writing, as they run as root. -You just have to install as a non-admin user and then use "chown -R" to fix -the owner. - -=============================================================================== -SECTION SIX: Miscellaneous -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Maintained By Paul Blackman, Email:ictinus@lake.canberra.edu.au diff --git a/docs/textdocs/BUGS.txt b/docs/textdocs/BUGS.txt index 0bd12e8af0a..5fc069371b3 100644 --- a/docs/textdocs/BUGS.txt +++ b/docs/textdocs/BUGS.txt @@ -25,7 +25,7 @@ that list that may be able to help you. You may also like to look though the recent mailing list archives, which are conveniently accessible on the Samba web pages -at http://samba.canberra.edu.au/pub/samba/ +at http://samba.anu.edu.au/samba/ GENERAL INFO diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index 01bc277a20b..c9bd04f1c83 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -1,6 +1,9 @@ The main Samba ftp site is samba.anu.edu.au in pub/samba/. Contact samba-bugs@samba.anu.edu.au for help with this site. +The 'Source Only' sites may also contain binary packages as we are now +including them on samba.anu.edu.au/pub/samba/Binary_Packages + Mirror sites include: Source Only @@ -18,6 +21,8 @@ Source Only --- Germany --- ftp://ftp.uni-trier.de/pub/unix/network/samba/ ftp://ftp.gwdg.de/pub/server/samba/ +--- Greece --- + ftp://ftp.ntua.gr/pub/net/samba/ --- Japan --- ftp://ring.asahi-net.or.jp/archives/net/samba/ ftp://ring.aist.go.jp/archives/net/samba/ @@ -28,8 +33,12 @@ Source Only ftp://ftp.gbnet.net/pub/samba/ ftp://ftp.ntrl.net/pub/mirror/samba/ ftp://despair.capecod.net/pub/Samba/ +--- Poland --- + ftp://giswitch.sggw.waw.pl/pub/unix/samba/ --- Portugal --- ftp://ftp.ua.pt/pub/misc/samba/ +--- Romania --- + ftp.romus.ro/pub/Linux/Network/samba/ --- Russian Federation --- ftp://ftp.uic.nsu.ru/pub/vendors/samba/ --- United Kingdom --- @@ -75,7 +84,7 @@ There are several others. Give archie a try. Http sites include: =================== -http://samba.canberra.edu.au/pub/samba +http://samba.anu.edu.au/samba http://www.choc.satech.net.au/pub/samba/ diff --git a/docs/textdocs/UNIX_INSTALL.txt b/docs/textdocs/UNIX_INSTALL.txt index c189482ca41..d78c36a4c9c 100644 --- a/docs/textdocs/UNIX_INSTALL.txt +++ b/docs/textdocs/UNIX_INSTALL.txt @@ -15,7 +15,7 @@ try something like: Unfortunately, having said this, the man pages are sadly out of date and really need more effort to maintain them. Other sources of information -are pointed to by the Samba web site, http://samba.canberra.edu.au/pub/samba. +are pointed to by the Samba web site, http://samba.anu.edu.au/samba. STEP 1. Building the binaries -- cgit From 9a81cb171c178a85ecd045afafbce7d4b481344e Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Tue, 7 Oct 1997 04:50:53 +0000 Subject: Oops forgot to run the sgml converters that one last time. All done. Paul. --- docs/faq/Samba-Server-FAQ.html | 2 +- docs/faq/Samba-meta-FAQ.html | 2 +- docs/faq/Samba-meta-FAQ.txt | 4 ++-- docs/faq/sambafaq.html | 2 +- docs/faq/sambafaq.txt | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/faq/Samba-Server-FAQ.html b/docs/faq/Samba-Server-FAQ.html index 501ff1b1ed8..eadc3e26ede 100644 --- a/docs/faq/Samba-Server-FAQ.html +++ b/docs/faq/Samba-Server-FAQ.html @@ -39,7 +39,7 @@ Table of Contents <HR> <H1> Samba Server FAQ</H1> -<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.1, 23 Aug '97 +<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.3, 7 Oct '97 <P><HR><EM> This is the <EM>Server</EM> Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. A general diff --git a/docs/faq/Samba-meta-FAQ.html b/docs/faq/Samba-meta-FAQ.html index 7821083740d..5a70808867b 100644 --- a/docs/faq/Samba-meta-FAQ.html +++ b/docs/faq/Samba-meta-FAQ.html @@ -37,7 +37,7 @@ Table of Contents <HR> <H1> Samba meta FAQ</H1> -<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.1, 23 Aug '97 +<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.3, 7 Oct '97 <P><HR><EM> This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It contains overview information for the Samba suite of programs, a diff --git a/docs/faq/Samba-meta-FAQ.txt b/docs/faq/Samba-meta-FAQ.txt index 4fb1ed65442..65d9a57ff62 100644 --- a/docs/faq/Samba-meta-FAQ.txt +++ b/docs/faq/Samba-meta-FAQ.txt @@ -1,6 +1,6 @@ Samba meta FAQ - Dan Shearer & Paul Blackman, ictinus@lake.canberra.edu.au - v 0.1, 23 Aug '97 + Dan Shearer & Paul Blackman, ictinus@samba.anu.edu.au + v 0.3, 7 Oct '97 This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It contains diff --git a/docs/faq/sambafaq.html b/docs/faq/sambafaq.html index 9e3d21ad137..9c45d524dd3 100644 --- a/docs/faq/sambafaq.html +++ b/docs/faq/sambafaq.html @@ -45,7 +45,7 @@ Table of Contents <HR> <H1> Samba FAQ</H1> -<H2>Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.7, June '97 +<H2>Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.8, June '97 <P><HR><EM> This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server allows file and printer connections from clients such as Windows, diff --git a/docs/faq/sambafaq.txt b/docs/faq/sambafaq.txt index 49cfa479fe9..7108846ae67 100644 --- a/docs/faq/sambafaq.txt +++ b/docs/faq/sambafaq.txt @@ -1,6 +1,6 @@ Samba FAQ - Paul Blackman, ictinus@lake.canberra.edu.au - v 0.7, June '97 + Paul Blackman, ictinus@samba.anu.edu.au + v 0.8, June '97 This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server allows file -- cgit From 5a38eaac75a6bede2d946f69cf664d7ca3989b55 Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Tue, 7 Oct 1997 04:56:02 +0000 Subject: More references to samba.canberra Mental note: always commit from root directory. :^o Paul. --- README | 6 +++--- examples/misc/extra_smbstatus | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index ba982448e14..30103241841 100644 --- a/README +++ b/README @@ -45,7 +45,7 @@ printers) from unix, Netware and other operating systems - a tar extension to the client for backing up PCs For a much better overview have a look at the web site at -http://samba.canberra.edu.au/pub/samba, and browse the user survey. +http://samba.anu.edu.au/samba, and browse the user survey. Related packages include: @@ -141,12 +141,12 @@ WEB SITE A Samba WWW site has been setup with lots of useful info. Connect to: -http://samba.canberra.edu.au/pub/samba/ +http://samba.anu.edu.au/samba/ As well as general information and documentation, this also has searchable archives of the mailing list and a user survey that shows who else is using this package. Have you registered with the survey yet? :-) It is maintained by Paul Blackman (thanks Paul!). You can contact him -at ictinus@lake.canberra.edu.au. +at ictinus@samba.anu.edu.au. diff --git a/examples/misc/extra_smbstatus b/examples/misc/extra_smbstatus index 363e7f67af5..584284feb34 100644 --- a/examples/misc/extra_smbstatus +++ b/examples/misc/extra_smbstatus @@ -46,5 +46,5 @@ Cheers, | | "Spend a little love and get high" _/ \_ | - Lenny Kravitz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -~~~~ SAMBA Web Pages: http://samba.canberra.edu.au/pub/samba/samba.html ~~~~~ +~~~~~~~~~~~~~~ SAMBA Web Pages: http://samba.anu.edu.au/samba/ ~~~~~~~~~~~~~~ -- cgit From bf1f8b1567cb46e3e73ae8dbb26f6228cf519c1f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 7 Oct 1997 11:14:27 +0000 Subject: get rid of SIGCLD_IGNORE for HPUX. A user reported it causing lots of defunct smbd processes. Andrew --- source/include/includes.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/include/includes.h b/source/include/includes.h index 2329553d234..d1afc34de92 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -563,7 +563,9 @@ char *mktemp(char *); /* No standard include */ #define USE_SETSID #define USE_SETRES #define DEFAULT_PRINTING PRINT_HPUX -#define SIGCLD_IGNORE +/* Ken Weiss <krweiss@ucdavis.edu> tells us that SIGCLD_IGNORE is + not good for HPUX */ +/* #define SIGCLD_IGNORE */ #endif /* HPUX */ -- cgit From bef10e388ac8661afc465a64524ba55f8c5bea0c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 7 Oct 1997 11:18:26 +0000 Subject: get rid of SIGCLD_IGNORE for HPUX. A user reported it causing lots of defunct smbd processes. Andrew --- source/include/includes.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/include/includes.h b/source/include/includes.h index e66ceb2d70c..4e48e87a7c1 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -563,7 +563,9 @@ char *mktemp(char *); /* No standard include */ #define USE_SETSID #define USE_SETRES #define DEFAULT_PRINTING PRINT_HPUX -#define SIGCLD_IGNORE +/* Ken Weiss <krweiss@ucdavis.edu> tells us that SIGCLD_IGNORE is + not good for HPUX */ +/* #define SIGCLD_IGNORE */ #endif /* HPUX */ -- cgit From b12b3626fd9ccc9cdf2111937b3ee344da361b1f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 7 Oct 1997 14:36:22 +0000 Subject: increase the debug level in the "added interface" debug line --- source/lib/interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/lib/interface.c b/source/lib/interface.c index 940af1eccf4..147425d0fc1 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -337,9 +337,9 @@ static void interpret_interfaces(char *s, struct interface **interfaces, iface->next = NULL; (*interfaces) = last_iface = iface; - DEBUG(1,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); + DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip))); + DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); + DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); } -- cgit From d98f9bbbdef02e46428c6eb954ebc5513bbc5c1c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 7 Oct 1997 14:36:51 +0000 Subject: increase the debug level in the "added interface" debug line --- source/lib/interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/lib/interface.c b/source/lib/interface.c index 940af1eccf4..147425d0fc1 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -337,9 +337,9 @@ static void interpret_interfaces(char *s, struct interface **interfaces, iface->next = NULL; (*interfaces) = last_iface = iface; - DEBUG(1,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); + DEBUG(2,("Added interface ip=%s ",inet_ntoa(iface->ip))); + DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); + DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); } -- cgit From 3e16fc01ed748129c1587acc6330730f3cfbf77a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 7 Oct 1997 14:38:31 +0000 Subject: increase the debug level in the "client requested max ..." debug line --- source/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index f3a8ad22b8a..31915e6acac 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -598,7 +598,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); - DEBUG(1,(" Client requested max send size of %d\n", max_send)); + DEBUG(5,(" Client requested max send size of %d\n", max_send)); done_sesssetup = True; -- cgit From b37e21273e81b875876e8e8ddf6804714044ffd8 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 7 Oct 1997 14:58:07 +0000 Subject: pipes.c: some routines to create LSA RPC packets. none of them are used. lsaparse.c: smbparse.c: smb.h: more tidy-up. --- source/include/proto.h | 1 + source/include/smb.h | 47 ++++++---- source/lsaparse.c | 14 +++ source/smbd/pipes.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++- source/smbparse.c | 3 +- 5 files changed, 285 insertions(+), 18 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 202b1511504..8f8ec5aa8a1 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -312,6 +312,7 @@ BOOL remove_share_oplock(int fnum, share_lock_token token); /*The following definitions come from lsaparse.c */ +char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align); char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align); char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align); char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align); diff --git a/source/include/smb.h b/source/include/smb.h index 43e402359f0..4850b33e494 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -331,16 +331,6 @@ typedef struct domsid2_info } DOM_SID2; -/* DOM_SID3 - domain SID structure - SIDs stored in unicode */ -typedef struct domsid3_info -{ - UNISTR str; /* domain SID unicode string */ - uint32 undoc; /* value is 0 */ - uint32 type1; /* value is 1 */ - uint32 type2; /* value is 5 or 3 */ - -} DOM_SID3; - /* DOM_RID2 - domain RID structure */ typedef struct domrid2_info { @@ -409,8 +399,8 @@ typedef struct id_info_1 DOM_LOGON_ID logon_id; /* logon ID */ UNIHDR hdr_user_name; /* user name unicode header */ UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ - ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ - ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ + ARC4_OWF arc4_lm_owf; /* rc4 LM OWF Password */ + ARC4_OWF arc4_nt_owf; /* rc4 NT OWF Password */ UNISTR2 uni_domain_name; /* domain name unicode string */ UNISTR2 uni_user_name; /* user name unicode string */ UNISTR2 uni_workgroup_name; /* workgroup name unicode string */ @@ -463,10 +453,11 @@ typedef struct rpc_hdr_info typedef struct dom_query_info { uint16 uni_dom_max_len; /* domain name string length * 2 */ + uint16 padding; /* 2 padding bytes? */ uint16 uni_dom_str_len; /* domain name string length * 2 */ uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ - UNISTR uni_domain_name; /* domain name (unicode string) */ + UNISTR2 uni_domain_name; /* domain name (unicode string) */ DOM_SID dom_sid; /* domain SID */ } DOM_QUERY; @@ -475,14 +466,25 @@ typedef struct dom_query_info typedef DOM_QUERY DOM_QUERY_3; typedef DOM_QUERY DOM_QUERY_5; +#define POL_HND_SIZE 20 + /* LSA_POL_HND */ typedef struct lsa_policy_info { - uint8 data[20]; /* policy handle */ + uint8 data[POL_HND_SIZE]; /* policy handle */ } LSA_POL_HND; +/* LSA_R_OPEN_POL - response to LSA Open Policy */ +typedef struct lsa_r_open_pol_info +{ + LSA_POL_HND pol; /* policy handle */ + + uint32 status; /* return code */ + +} LSA_R_OPEN_POL; + /* LSA_Q_QUERY_INFO - LSA query info policy */ typedef struct lsa_query_info { @@ -530,7 +532,6 @@ typedef struct dom_ref_info /* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */ typedef struct lsa_q_lookup_sids { - LSA_POL_HND pol_hnd; /* policy handle */ uint32 num_entries; uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ @@ -669,7 +670,7 @@ typedef struct lsa_q_srv_pwset_info /* LSA_R_SRV_PWSET */ typedef struct lsa_r_srv_pwset_info { - DOM_CHAL srv_chal; /* server-calculated credentials */ + DOM_CRED srv_cred; /* server-calculated credentials */ uint32 status; /* return code */ @@ -1040,8 +1041,10 @@ typedef struct { smb_shm_offset_t next_share_mode_entry; int pid; +#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; +#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } share_mode_entry; @@ -1050,8 +1053,10 @@ typedef struct typedef struct { int pid; +#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; +#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } min_share_mode_entry; @@ -1077,7 +1082,11 @@ struct connect_record }; #ifndef LOCKING_VERSION +#ifdef USE_OPLOCKS #define LOCKING_VERSION 4 +#else /* USE_OPLOCKS */ +#define LOCKING_VERSION 3 +#endif /* USE_OPLOCKS */ #endif /* LOCKING_VERSION */ #if !defined(FAST_SHARE_MODES) @@ -1093,7 +1102,11 @@ struct connect_record #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 +#ifdef USE_OPLOCKS #define SMF_ENTRY_LENGTH 20 +#else /* USE_OPLOCKS */ +#define SMF_ENTRY_LENGTH 16 +#endif /* USE_OPLOCKS */ /* * Share mode record offsets. @@ -1104,8 +1117,10 @@ struct connect_record #define SME_SHAREMODE_OFFSET 8 #define SME_PID_OFFSET 12 +#ifdef USE_OPLOCKS #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 +#endif /* USE_OPLOCKS */ #endif /* FAST_SHARE_MODES */ diff --git a/source/lsaparse.c b/source/lsaparse.c index 70d4f493800..43e7ef1d402 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -24,6 +24,20 @@ extern int DEBUGLEVEL; +/******************************************************************* +reads or writes an LSA_R_OPEN_POL structure. +********************************************************************/ +char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align) +{ + if (r_p == NULL) return NULL; + + q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align); + + RW_IVAL(io, q, r_p->status, 0); q += 4; + + return q; +} + /******************************************************************* reads or writes an LSA_Q_QUERY_INFO structure. ********************************************************************/ diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index a465e911459..0fb8a89c9e1 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -2,7 +2,9 @@ Unix SMB/Netbios implementation. Version 1.9. Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Andrew Tridgell 1992-1997, + Paul Ashton 1997, + Luke Kenneth Casson Leighton 1996-1997. 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 @@ -51,6 +53,9 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { "lsarpc", +#if 0 + "NETLOGON", +#endif NULL }; @@ -357,3 +362,234 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } + +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +/* identauth >= 2^32 can be detected because it will be specified in hex */ +static void init_dom_sid(DOM_SID *sid, char *domsid) +{ + int identauth; + char *p; + + DEBUG(4,("netlogon domain SID: %s\n", domsid)); + + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + sid->sid_no = atoi(p); + + /* identauth in decimal should be < 2^32 */ + /* identauth in hex should be >= 2^32 */ + identauth = atoi(strtok(0,"-")); + + DEBUG(4,("netlogon rev %d\n", sid->sid_no)); + DEBUG(4,("netlogon %s ia %d\n", p, identauth)); + + sid->id_auth[0] = 0; + sid->id_auth[1] = 0; + sid->id_auth[2] = (identauth & 0xff000000) >> 24; + sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; + sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; + sid->id_auth[5] = (identauth & 0x000000ff); + + sid->num_auths = 0; + + while ((p = strtok(0, "-")) != NULL) + { + sid->sub_auths[sid->num_auths++] = atoi(p); + } +} + +static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) +{ + if (hdr == NULL) return; + + hdr->major = 5; /* RPC version 5 */ + hdr->minor = 0; /* minor version 0 */ + hdr->pkt_type = 2; /* RPC response packet */ + hdr->frag = 3; /* first frag + last frag */ + hdr->pack_type = 1; /* packed data representation */ + hdr->frag_len = data_len; /* fragment length, fill in later */ + hdr->auth_len = 0; /* authentication length */ + hdr->call_id = call_id; /* call identifier - match incoming RPC */ + hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ + hdr->context_id = 0; /* presentation context identifier */ + hdr->cancel_count = 0; /* cancel count */ + hdr->reserved = 0; /* reserved */ +} + +static void init_rpc_reply(char *inbuf, char *q, char *base, int data_len) +{ + uint32 callid = RIVAL(inbuf, 12); + RPC_HDR hdr; + + create_rpc_reply(&hdr, callid, data_len); + smb_io_rpc_hdr(False, &hdr, q, base, 4); +} + +static int lsa_reply_open_policy(char *q, char *base) +{ + char *start = q; + LSA_R_OPEN_POL r_o; + + /* set up the LSA QUERY INFO response */ + bzero(&(r_o.pol.data), POL_HND_SIZE); + r_o.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_open_pol(False, &r_o, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = len + (terminate != 0 ? 1 : 0); + str->undoc = 0; + str->uni_str_len = len; + + /* store the string (null-terminated copy) */ + PutUniCode((char *)str->buffer, buf); + + /* overwrite the last character: some strings are terminated with 4 not 0 */ + str->buffer[len] = (uint16)terminate; +} + +static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +{ + int domlen = strlen(dom_name); + + d_q->uni_dom_max_len = domlen * 2; + d_q->padding = 0; + d_q->uni_dom_str_len = domlen * 2; + + d_q->buffer_dom_name = 0; /* domain buffer pointer */ + d_q->buffer_dom_sid = 0; /* domain sid pointer */ + + /* NOT null-terminated: 4-terminated instead! */ + init_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + + init_dom_sid(&(d_q->dom_sid), dom_sid); +} + +static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, + char *dom_name, char *dom_sid) +{ + char *start = q; + LSA_R_QUERY_INFO r_q; + + /* set up the LSA QUERY INFO response */ + + r_q.undoc_buffer = 1; /* not null */ + r_q.info_class = q_q->info_class; + + init_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_query(False, &r_q, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +{ + memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); + r_c->status = status; +} + +#if 0 + char chal[8]; + /* PAXX: set these to random values */ + for (int i = 0; i < 8; i+++) + { + chal[i] = 0xA5; + } +#endif + +static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, + char chal[8]) +{ + char *start = q; + LSA_R_REQ_CHAL r_c; + + /* set up the LSA REQUEST CHALLENGE response */ + + init_lsa_r_req_chal(&r_c, chal, 0); + + /* store the response in the SMB stream */ + q = lsa_io_r_req_chal(False, &r_c, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) +{ + memcpy(cred->data, resp_cred, sizeof(cred->data)); +} + +static void init_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, + char resp_cred[8], NEG_FLAGS *flgs, int status) +{ + init_lsa_chal(&(r_a->srv_chal), resp_cred); + memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); + r_a->status = status; +} + +static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, + char resp_cred[8], int status) +{ + char *start = q; + LSA_R_AUTH_2 r_a; + + /* set up the LSA AUTH 2 response */ + + init_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + + /* store the response in the SMB stream */ + q = lsa_io_r_auth_2(False, &r_a, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + +static void init_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +{ + init_lsa_chal(&(cred->challenge), srv_chal); + cred->timestamp = srv_time; +} + + +static void init_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, + char srv_chal[8], UTIME srv_time, int status) +{ + init_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + r_a->status = status; +} + +static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + int status) +{ + char *start = q; + LSA_R_SRV_PWSET r_s; + + /* set up the LSA Server Password Set response */ + init_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + + /* store the response in the SMB stream */ + q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + diff --git a/source/smbparse.c b/source/smbparse.c index 95390522ff5..7ea140f7cb7 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -416,7 +416,7 @@ char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align) q = align_offset(q, base, align); - RW_PCVAL(io, q, pol->data, 20); q += 20; + RW_PCVAL(io, q, pol->data, POL_HND_SIZE); q += POL_HND_SIZE; return q; } @@ -448,6 +448,7 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) RW_SVAL(io, q, d_q->uni_dom_max_len, 0); q += 2; /* domain name string length * 2 */ + RW_SVAL(io, q, d_q->padding , 0); q += 2; /* 2 padding bytes */ RW_SVAL(io, q, d_q->uni_dom_str_len, 0); q += 2; /* domain name string length * 2 */ RW_IVAL(io, q, d_q->buffer_dom_name, 0); q += 4; /* undocumented domain name string buffer pointer */ -- cgit From 67c1e87e8fda724da6dd3663641639167dd33a16 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Tue, 7 Oct 1997 16:01:08 +0000 Subject: JHT ==> Fixing blocksize argument. Patch by: Llyod Whiteman <lwhitman@stm2.nrl.navy.mil> --- source/script/smbtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/script/smbtar b/source/script/smbtar index a947476dc6b..dcf01edb208 100644 --- a/source/script/smbtar +++ b/source/script/smbtar @@ -88,7 +88,7 @@ while getopts rivl:b:d:N:s:p:x:u:Xt: c; do server="$OPTARG" ;; b) # specify [b]locksize - blocksize="blocksize $OPTARG" + blocksize="$OPTARG" case "$OPTARG" in [0-9]*) ;; *) echo >&2 "$0: Error, block size not numeric: -b $OPTARG" -- cgit From bef12478d212a950578843d6d4dece1f153bfd25 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 7 Oct 1997 18:18:10 +0000 Subject: pipes.c: more static unused functions in pipes.c for the LSA RPC stream. smb.h: corrections and altercations over the documentation lsaparse.c: reflecting alterations in LSA structures... --- source/include/smb.h | 9 +-- source/lsaparse.c | 5 +- source/smbd/pipes.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 191 insertions(+), 23 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 4850b33e494..3adb3e5a4cb 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -677,6 +677,7 @@ typedef struct lsa_r_srv_pwset_info } LSA_R_SRV_PWSET; #define LSA_MAX_GROUPS 32 +#define LSA_MAX_SIDS 32 /* LSA_USER_INFO */ typedef struct lsa_q_user_info @@ -714,8 +715,8 @@ typedef struct lsa_q_user_info uint32 buffer_dom_id; /* undocumented logon domain id pointer */ char padding[40]; /* unused padding bytes? */ - uint32 num_sids; /* 0 - num_sids */ - uint32 buffer_sids; /* NULL - undocumented pointer to SIDs. */ + uint32 num_other_sids; /* 0 - num_sids */ + uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */ UNISTR2 uni_user_name; /* username unicode string */ UNISTR2 uni_full_name; /* user's full name unicode string */ @@ -730,8 +731,8 @@ typedef struct lsa_q_user_info UNISTR2 uni_logon_srv; /* logon server unicode string */ UNISTR2 uni_logon_dom; /* logon domain unicode string */ - DOM_SID undoc_dom_sids[2]; /* undocumented - domain SIDs */ DOM_SID dom_sid; /* domain SID */ + DOM_SID other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */ } LSA_USER_INFO; @@ -750,7 +751,7 @@ typedef struct lsa_r_sam_logon_info DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ uint32 buffer_user; - LSA_USER_INFO user; + LSA_USER_INFO *user; uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ diff --git a/source/lsaparse.c b/source/lsaparse.c index 43e7ef1d402..2113b19cd33 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -403,7 +403,10 @@ char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ RW_IVAL(io, q, r_l->buffer_user, 0); q += 4; - q = lsa_io_user_info(io, &(r_l->user), q, base, align); + if (r_l->buffer_user != 0) + { + q = lsa_io_user_info(io, r_l->user, q, base, align); + } RW_IVAL(io, q, r_l->auth_resp, 0); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 0fb8a89c9e1..95b69ef4d97 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -28,6 +28,7 @@ #include "includes.h" #include "trans2.h" +#include "nterr.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) @@ -371,7 +372,7 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ /* identauth >= 2^32 can be detected because it will be specified in hex */ -static void init_dom_sid(DOM_SID *sid, char *domsid) +static void make_dom_sid(DOM_SID *sid, char *domsid) { int identauth; char *p; @@ -422,7 +423,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void init_rpc_reply(char *inbuf, char *q, char *base, int data_len) +static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; @@ -447,7 +448,14 @@ static int lsa_reply_open_policy(char *q, char *base) return q - start; } -static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) +{ + hdr->uni_max_len = max_len; + hdr->uni_str_len = len; + hdr->undoc = terminate; +} + +static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) { /* set up string lengths. add one if string is not null-terminated */ str->uni_max_len = len + (terminate != 0 ? 1 : 0); @@ -461,7 +469,7 @@ static void init_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } -static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) { int domlen = strlen(dom_name); @@ -473,9 +481,9 @@ static void init_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) d_q->buffer_dom_sid = 0; /* domain sid pointer */ /* NOT null-terminated: 4-terminated instead! */ - init_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); - init_dom_sid(&(d_q->dom_sid), dom_sid); + make_dom_sid(&(d_q->dom_sid), dom_sid); } static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, @@ -489,7 +497,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, r_q.undoc_buffer = 1; /* not null */ r_q.info_class = q_q->info_class; - init_dom_query(&r_q.dom.id5, dom_name, dom_sid); + make_dom_query(&r_q.dom.id5, dom_name, dom_sid); r_q.status = 0x0; @@ -500,7 +508,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, return q - start; } -static void init_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); r_c->status = status; @@ -523,7 +531,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, /* set up the LSA REQUEST CHALLENGE response */ - init_lsa_r_req_chal(&r_c, chal, 0); + make_lsa_r_req_chal(&r_c, chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4); @@ -532,15 +540,15 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, return q - start; } -static void init_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) +static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) { memcpy(cred->data, resp_cred, sizeof(cred->data)); } -static void init_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, +static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, char resp_cred[8], NEG_FLAGS *flgs, int status) { - init_lsa_chal(&(r_a->srv_chal), resp_cred); + make_lsa_chal(&(r_a->srv_chal), resp_cred); memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); r_a->status = status; } @@ -553,7 +561,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, /* set up the LSA AUTH 2 response */ - init_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); /* store the response in the SMB stream */ q = lsa_io_r_auth_2(False, &r_a, q, base, 4); @@ -562,17 +570,17 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void init_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) { - init_lsa_chal(&(cred->challenge), srv_chal); + make_lsa_chal(&(cred->challenge), srv_chal); cred->timestamp = srv_time; } -static void init_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, +static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, char srv_chal[8], UTIME srv_time, int status) { - init_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); r_a->status = status; } @@ -584,7 +592,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ - init_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); /* store the response in the SMB stream */ q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); @@ -593,3 +601,159 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, return q - start; } +static void make_lsa_user_info(LSA_USER_INFO *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *logon_script, + char *profile_path, + char *home_dir, + char *dir_drive, + + uint16 logon_count, + uint16 bad_pw_count, + + uint32 user_id, + uint32 group_id, + uint32 num_groups, + DOM_GID *gids, + uint32 user_flgs, + + char sess_key[16], + + char *logon_srv, + char *logon_dom, + + char *dom_sid, + char *other_sids) /* space-delimited set of SIDs */ +{ + /* only cope with one "other" sid, right now. */ + /* need to count the number of space-delimited sids */ + int i; + int num_other_sids = other_sids != NULL ? 1 : 0; + + int len_user_name = strlen(user_name ); + int len_full_name = strlen(full_name ); + int len_logon_script = strlen(logon_script); + int len_profile_path = strlen(profile_path); + int len_home_dir = strlen(home_dir ); + int len_dir_drive = strlen(dir_drive ); + + int len_logon_srv = strlen(logon_srv); + int len_logon_dom = strlen(logon_dom); + + usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ + + usr->logon_time = *logon_time; + usr->logoff_time = *logoff_time; + usr->kickoff_time = *kickoff_time; + usr->pass_last_set_time = *pass_last_set_time; + usr->pass_can_change_time = *pass_can_change_time; + usr->pass_must_change_time = *pass_must_change_time; + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); + + usr->logon_count = logon_count; + usr->bad_pw_count = bad_pw_count; + + usr->user_id = user_id; + usr->group_id = group_id; + usr->num_groups = num_groups; + usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ + usr->user_flgs = user_flgs; + + if (sess_key != NULL) + { + memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); + } + else + { + bzero(usr->sess_key, sizeof(usr->sess_key)); + } + + make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); + make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); + + usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ + + bzero(usr->padding, sizeof(usr->padding)); + + usr->num_other_sids = num_other_sids; + usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); + + usr->num_groups2 = num_groups; + for (i = 0; i < num_groups; i++) + { + usr->gids[i] = gids[i]; + } + + make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); + make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); + + make_dom_sid(&(usr->dom_sid), dom_sid); + make_dom_sid(&(usr->other_sids[0]), other_sids); +} + + +static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + LSA_USER_INFO *user_info) +{ + char *start = q; + LSA_R_SAM_LOGON r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + + /* store the user information, if there is any. */ + r_s.user = user_info; + r_s.buffer_user = user_info != NULL ? 1 : 0; + r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logon(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + + +static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, + char srv_cred[8], UTIME srv_time, + uint32 status) +{ + char *start = q; + LSA_R_SAM_LOGOFF r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + + r_s.status = status; + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} -- cgit From 1e1366ddc5542283a37debdf830ca139bbade1b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 7 Oct 1997 18:46:19 +0000 Subject: locking.c: Added fix for race condition in slow share mode code. lsaparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. pipes.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. server.c: Fixed last known oplock race condition. smb.h: Re-removed USE_OPLOCK defines - someone checked in an old version. smbparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. Jeremy (jallison@whistle.com) --- source/include/smb.h | 15 ---------- source/locking/locking.c | 71 ++++++++++++++++++++++++++++++++++++++---------- source/lsaparse.c | 2 ++ source/smbd/pipes.c | 4 +++ source/smbd/server.c | 29 ++++++++++++++++++++ source/smbparse.c | 2 ++ 6 files changed, 93 insertions(+), 30 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 3adb3e5a4cb..c347202743c 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -1042,10 +1042,8 @@ typedef struct { smb_shm_offset_t next_share_mode_entry; int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } share_mode_entry; @@ -1054,10 +1052,8 @@ typedef struct typedef struct { int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } min_share_mode_entry; @@ -1083,11 +1079,7 @@ struct connect_record }; #ifndef LOCKING_VERSION -#ifdef USE_OPLOCKS #define LOCKING_VERSION 4 -#else /* USE_OPLOCKS */ -#define LOCKING_VERSION 3 -#endif /* USE_OPLOCKS */ #endif /* LOCKING_VERSION */ #if !defined(FAST_SHARE_MODES) @@ -1103,11 +1095,7 @@ struct connect_record #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 -#ifdef USE_OPLOCKS #define SMF_ENTRY_LENGTH 20 -#else /* USE_OPLOCKS */ -#define SMF_ENTRY_LENGTH 16 -#endif /* USE_OPLOCKS */ /* * Share mode record offsets. @@ -1117,11 +1105,8 @@ struct connect_record #define SME_USEC_OFFSET 4 #define SME_SHAREMODE_OFFSET 8 #define SME_PID_OFFSET 12 - -#ifdef USE_OPLOCKS #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 -#endif /* USE_OPLOCKS */ #endif /* FAST_SHARE_MODES */ diff --git a/source/locking/locking.c b/source/locking/locking.c index 6e321d0626e..639bc7be0ba 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -25,6 +25,10 @@ May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode locking to deal with multiple share modes per open file. + + September 1997. Jeremy Allison (jallison@whistle.com). Added oplock + support. + */ #include "includes.h" @@ -726,13 +730,60 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { int old_umask; + BOOL gotlock = False; unbecome_user(); old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; + #ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", + fname, strerror(errno))); + close(fd); + return False; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { @@ -750,18 +801,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok } } - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - close(fd); - return False; - } - - *ptok = (share_lock_token)fd; - return True; + *ptok = (share_lock_token)fd; + return True; } /******************************************************************* @@ -781,7 +822,7 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok ret = False; } - close((int)token); + close(fd); return ret; } diff --git a/source/lsaparse.c b/source/lsaparse.c index 2113b19cd33..b1d9d739240 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -24,6 +24,7 @@ extern int DEBUGLEVEL; +#if 0 /* NEED TO DO THIS TO GET A COMPILE - LUKE PLEASE CHECK THIS !!! */ /******************************************************************* reads or writes an LSA_R_OPEN_POL structure. ********************************************************************/ @@ -446,6 +447,7 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i return q; } +#endif /* 0 LUKE PLEASE CHECK !! */ #if 0 /******************************************************************* reads or writes a structure. diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 95b69ef4d97..ffa64a4e808 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -364,6 +364,8 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } +#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */ + /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -757,3 +759,5 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } + +#endif /* LUKE PLEASE CHECK THIS !! */ diff --git a/source/smbd/server.c b/source/smbd/server.c index 4f5b01ba91e..92c219c71b3 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -2455,6 +2455,9 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); } oplock_port = ntohs(sock_name.sin_port); + DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", + getpid(), oplock_port)); + return True; } @@ -2545,6 +2548,31 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, } break; + /* + * Keep this as a debug case - eventually we can remove it. + */ + case 0x8001: + DEBUG(0,("process_local_message: Received unsolicited break \ +reply - dumping info.\n")); + + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: ubr: incorrect length for reply \ +(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + + } + return False; + default: DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", (unsigned int)SVAL(msg_start,0))); @@ -2860,6 +2888,7 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", share_entry->pid, share_entry->op_port, dev, inode)); if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) return False; + continue; } break; diff --git a/source/smbparse.c b/source/smbparse.c index 7ea140f7cb7..ae1f4f4b253 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -456,7 +456,9 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) if (d_q->buffer_dom_name != 0) { +#if 0 /* REMOVED AS WON'T COMPILE AS IS - LUKE PLEASE CHECK !!!!! */ q = smb_io_unistr(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ +#endif } if (d_q->buffer_dom_sid != 0) { -- cgit From 1c510a4c3c59ebdf170b73c0fb082d0fa1fabf25 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 7 Oct 1997 19:24:44 +0000 Subject: Fixed nasty (but rare) race mode condition with slow share mode code. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 64 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index 868902963fe..b86ef76a2b8 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -612,13 +612,59 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { int old_umask; + BOOL gotlock = False; unbecome_user(); old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; #ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", + strerror(errno))); + close(fd); + return False; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { @@ -636,18 +682,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok } } - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - close(fd); - return False; - } - - *ptok = (share_lock_token)fd; - return True; + *ptok = (share_lock_token)fd; + return True; } /******************************************************************* -- cgit From 707d0ec388c0045938f367e1d17919bfc8637fea Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Tue, 7 Oct 1997 22:04:05 +0000 Subject: I rewrote the name_mangle() and name_len(). The interface is the same, but I've simplified the code a bit and added a few comments. I tested the changes and the output is the same as that produced by the original (at least, it was in all of my tests). CRH --- source/lib/util.c | 111 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/source/lib/util.c b/source/lib/util.c index 611794c4a86..39d3c61b9e3 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -684,48 +684,61 @@ static int name_interpret(char *in,char *out) /**************************************************************************** mangle a name into netbios format + + Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum. ****************************************************************************/ -int name_mangle(char *In,char *Out,char name_type) -{ - fstring name; - char buf[20]; - char *in = (char *)&buf[0]; - char *out = (char *)Out; - char *p, *label; - int i; +int name_mangle( char *In, char *Out, char name_type ) + { + int i; + int c; + int len; + char buf[20]; + char *p = Out; + + /* Safely copy the input string, In, into buf[]. */ + (void)memset( buf, 0, 20 ); + if( '*' == In[0] ) + buf[0] = '*'; + else + (void)sprintf( buf, "%-15.15s%c", In, name_type ); - if (In[0] != '*') { - StrnCpy(name,In,sizeof(name)-1); - sprintf(buf,"%-15.15s%c",name,name_type); - } else { - buf[0]='*'; - memset(&buf[1],0,16); - } + /* Place the length of the first field into the output buffer. */ + p[0] = 32; + p++; - *out++ = 32; - for (i=0;i<16;i++) { - char c = toupper(in[i]); - out[i*2] = (c>>4) + 'A'; - out[i*2+1] = (c & 0xF) + 'A'; - } - out[32]=0; - out += 32; - - label = scope; - while (*label) + /* Now convert the name to the rfc1001/1002 format. */ + for( i = 0; i < 16; i++ ) { - p = strchr(label, '.'); - if (p == 0) - p = label + strlen(label); - *out++ = p - label; - memcpy(out, label, p - label); - out += p - label; - label += p - label + (*p == '.'); + c = toupper( buf[i] ); + p[i*2] = ( (c >> 4) & 0x000F ) + 'A'; + p[(i*2)+1] = (c & 0x000F) + 'A'; } - *out = 0; - return(name_len(Out)); -} + p += 32; + p[0] = '\0'; + /* Add the scope string. */ + for( i = 0, len = 0; NULL != scope; i++, len++ ) + { + switch( scope[i] ) + { + case '\0': + p[0] = len; + if( len > 0 ) + p[len+1] = 0; + return( name_len(Out) ); + case '.': + p[0] = len; + p += (len + 1); + len = 0; + break; + default: + p[len+1] = scope[i]; + break; + } + } + + return( name_len(Out) ); + } /* name_mangle */ /******************************************************************* check if a file exists @@ -2555,21 +2568,27 @@ int name_extract(char *buf,int ofs,char *name) strcpy(name,""); if (d < -50 || d > 50) return(0); return(name_interpret(p,name)); -} +} - /**************************************************************************** return the total storage length of a mangled name ****************************************************************************/ -int name_len(char *s) -{ - char *s0=s; - unsigned char c = *(unsigned char *)s; - if ((c & 0xC0) == 0xC0) +int name_len( char *s ) + { + int len; + + /* If the two high bits of the byte are set, return 2. */ + if( 0xC0 == (*(unsigned char *)s & 0xC0) ) return(2); - while (*s) s += (*s)+1; - return(PTR_DIFF(s,s0)+1); -} + + /* Add up the length bytes. */ + for( len = 1; (*s); s += (*s) + 1 ) + { + len += *s + 1; + } + + return( len ); + } /* name_len */ /**************************************************************************** send a single packet to a port on another machine -- cgit From cc50955a2760f1de7e80b91408a7c0806f6eb44c Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Wed, 8 Oct 1997 00:21:39 +0000 Subject: ipc.c: Added ERROR_MORE_DATA error if client buffer too small. server.c: Allow admin_user on read only shares. I think this is safe but it needs looking at. Jeremy (jallison@whistle.com) --- source/smbd/ipc.c | 2 +- source/smbd/server.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index b9355c4ec07..6da9562c9f4 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1074,7 +1074,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); diff --git a/source/smbd/server.c b/source/smbd/server.c index 92c219c71b3..290181fb9ee 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -3167,8 +3167,17 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de } /* admin user check */ - if (user_in_list(user,lp_admin_users(snum)) && - !pcon->read_only) + + /* JRA - original code denied admin user if the share was + marked read_only. Changed as I don't think this is needed, + but old code left in case there is a problem here. + */ + if (user_in_list(user,lp_admin_users(snum)) +#if 0 + && !pcon->read_only) +#else + ) +#endif { pcon->admin_user = True; DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); -- cgit From 6e1164b7c55668ebd0b6e97d7f05409134b39c1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Wed, 8 Oct 1997 00:24:38 +0000 Subject: Added ERROR_MORE_DATA fix when replies have been truncated. Jeremy (jallison@whistle.com) --- source/smbd/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 9aaf03e6c4f..a0a4ec8fc73 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1074,7 +1074,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); -- cgit From 07b878e2027539b6721f41b9f5670d50d9da7071 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 8 Oct 1997 02:18:45 +0000 Subject: put this in 1.9.17 also ... change the semantics of hosts allow/hosts deny so that a global setting applies to all shares regardless of any settings on other shares. This allows us to immediately drop a connection if it does not come from a allowed host, without even parsing the first SMB packet. The next time we get a nasty security hole we can offer people the option of just setting their hosts allow line. If we drop a connection in this way we generate a "Not listening for calling name" response and then exit. --- docs/manpages/smb.conf.5 | 9 +++++---- source/smbd/server.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index a0a96f26ff6..5c4ce3375fe 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -720,10 +720,11 @@ then the "load printers" option is easier. A synonym for this parameter is 'hosts allow'. This parameter is a comma delimited set of hosts which are permitted to access -a services. If specified in the [global] section, matching hosts will be -allowed access to any service that does not specifically exclude them from -access. Specific services my have their own list, which override those -specified in the [global] section. +a service. + +If specified in the [global] section then it will apply to all +services, regardless of whether the individual service has a different +setting. You can specify the hosts by name or IP number. For example, you could restrict access to only the hosts on a Class C subnet with something like diff --git a/source/smbd/server.c b/source/smbd/server.c index 2bc0e023158..35a7c730be4 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -4068,6 +4068,23 @@ static void process(void) } } + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (!check_access(-1)) { + /* send a negative session response "not listining + on calling name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG(1,("%s Connection denied from %s\n", + timestring(),client_addr())); + send_smb(Client,(char *)buf); + exit_server("connection denied"); + } + } + + msg_type = CVAL(InBuffer,0); msg_flags = CVAL(InBuffer,1); type = CVAL(InBuffer,smb_com); -- cgit From 0b7049fae25957851a7f33d2bd500d8ecefc1ad5 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 8 Oct 1997 11:47:46 +0000 Subject: updating lsaparse.c and smbparse.c in line with changes to pipes.c and smb.h from yesterday. --- source/lsaparse.c | 17 ++++++++--------- source/smbd/pipes.c | 4 ---- source/smbparse.c | 4 +--- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/source/lsaparse.c b/source/lsaparse.c index b1d9d739240..4b5c4f586a2 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -24,7 +24,6 @@ extern int DEBUGLEVEL; -#if 0 /* NEED TO DO THIS TO GET A COMPILE - LUKE PLEASE CHECK THIS !!! */ /******************************************************************* reads or writes an LSA_R_OPEN_POL structure. ********************************************************************/ @@ -298,7 +297,7 @@ char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int q = align_offset(q, base, align); - q = smb_io_chal(io, &(r_s->srv_chal), q, base, align); /* server challenge */ + q = smb_io_cred(io, &(r_s->srv_cred), q, base, align); /* server challenge */ RW_IVAL(io, q, r_s->status, 0); q += 4; @@ -351,8 +350,8 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali RW_IVAL(io, q, usr->buffer_dom_id, 0); q += 4; /* undocumented logon domain id pointer */ RW_PCVAL(io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ - RW_IVAL(io, q, usr->num_sids, 0); q += 4; /* 0 - num_sids */ - RW_IVAL(io, q, usr->buffer_sids, 0); q += 4; /* NULL - undocumented pointer to SIDs. */ + RW_IVAL(io, q, usr->num_other_sids, 0); q += 4; /* 0 - num_sids */ + RW_IVAL(io, q, usr->buffer_other_sids, 0); q += 4; /* NULL - undocumented pointer to SIDs. */ q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align); /* username unicode string */ q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align); /* user's full name unicode string */ @@ -370,10 +369,13 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align); /* logon server unicode string */ q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align); /* logon domain unicode string */ - q = smb_io_dom_sid(io, &(usr->undoc_dom_sids[0]), q, base, align); /* undocumented - domain SIDs */ - q = smb_io_dom_sid(io, &(usr->undoc_dom_sids[1]), q, base, align); /* undocumented - domain SIDs */ q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align); /* domain SID */ + for (i = 0; i < usr->num_other_sids; i++) + { + q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align); /* other domain SIDs */ + } + return q; } @@ -447,7 +449,6 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i return q; } -#endif /* 0 LUKE PLEASE CHECK !! */ #if 0 /******************************************************************* reads or writes a structure. @@ -463,5 +464,3 @@ reads or writes a structure. return q; } #endif - - diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index ffa64a4e808..95b69ef4d97 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -364,8 +364,6 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */ - /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -759,5 +757,3 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } - -#endif /* LUKE PLEASE CHECK THIS !! */ diff --git a/source/smbparse.c b/source/smbparse.c index ae1f4f4b253..0d93c2e8ad5 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -456,9 +456,7 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) if (d_q->buffer_dom_name != 0) { -#if 0 /* REMOVED AS WON'T COMPILE AS IS - LUKE PLEASE CHECK !!!!! */ - q = smb_io_unistr(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ -#endif + q = smb_io_unistr2(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ } if (d_q->buffer_dom_sid != 0) { -- cgit From d15aed8a9c58a7cc90befaee2d5a2752708f9327 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 8 Oct 1997 17:12:07 +0000 Subject: loadparm.c proto.h: added lp_domainsid() lsaparse.c smb.h: debugging structures and parsing functions pipes.c: finally got to the functions that will go into the RPC switch statement. --- source/include/proto.h | 5 +- source/include/smb.h | 4 +- source/lsaparse.c | 2 + source/param/loadparm.c | 4 ++ source/smbd/pipes.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 150 insertions(+), 5 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 8f8ec5aa8a1..fab69de3d1a 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -152,6 +152,7 @@ char *lp_socket_address(void); char *lp_nis_home_map_name(void); char *lp_announce_version(void); char *lp_netbios_aliases(void); +char *lp_domainsid(void); BOOL lp_dns_proxy(void); BOOL lp_wins_support(void); BOOL lp_wins_proxy(void); @@ -928,7 +929,7 @@ BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups); char *StrCpy(char *dest,char *src); char *StrnCpy(char *dest,char *src,int n); void putip(void *dest,void *src); -int name_mangle(char *In,char *Out,char name_type); +int name_mangle( char *In, char *Out, char name_type ); BOOL file_exist(char *fname,struct stat *sbuf); time_t file_modtime(char *fname); BOOL directory_exist(char *dname,struct stat *st); @@ -989,7 +990,7 @@ BOOL receive_message_or_smb(int smbfd, int oplock_fd, BOOL send_smb(int fd,char *buffer); char *name_ptr(char *buf,int ofs); int name_extract(char *buf,int ofs,char *name); -int name_len(char *s); +int name_len( char *s ); BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type); void msleep(int t); BOOL in_list(char *s,char *list,BOOL casesensitive); diff --git a/source/include/smb.h b/source/include/smb.h index c347202743c..9f5279fca00 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -326,6 +326,7 @@ typedef struct domsid2_info { uint32 type; /* value is 5 */ uint32 undoc; /* value is 0 */ + UNIHDR2 hdr; /* XXXX conflict between hdr and str for length */ UNISTR str; /* XXXX conflict between hdr and str for length */ @@ -488,7 +489,8 @@ typedef struct lsa_r_open_pol_info /* LSA_Q_QUERY_INFO - LSA query info policy */ typedef struct lsa_query_info { - uint16 info_class; /* info class (also a policy handle?) */ + LSA_POL_HND pol; /* policy handle */ + uint16 info_class; /* info class */ } LSA_Q_QUERY_INFO; diff --git a/source/lsaparse.c b/source/lsaparse.c index 4b5c4f586a2..9ea6f566b23 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -45,6 +45,8 @@ char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int al { if (q_q == NULL) return NULL; + q = smb_io_pol_hnd(io, &(q_q->pol), q, base, align); + RW_SVAL(io, q, q_q->info_class, 0); q += 2; return q; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index fb656aa627f..edc2d2b65f6 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -140,6 +140,7 @@ typedef struct char *szNISHomeMapName; char *szAnnounceVersion; /* This is initialised in init_globals */ char *szNetbiosAliases; + char *szDomainSID; int max_log_size; int mangled_stack; int max_xmit; @@ -436,6 +437,7 @@ struct parm_struct {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL}, {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars}, {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL}, + {"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL}, {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL}, {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL}, {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set}, @@ -839,6 +841,8 @@ FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName) FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion) FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases) +FN_GLOBAL_STRING(lp_domainsid,&Globals.szDomainSID) + FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy) diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 95b69ef4d97..06b785bd873 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -423,13 +423,13 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len) +static void make_rpc_reply(char *inbuf, char *q, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; create_rpc_reply(&hdr, callid, data_len); - smb_io_rpc_hdr(False, &hdr, q, base, 4); + smb_io_rpc_hdr(False, &hdr, q, q, 4); } static int lsa_reply_open_policy(char *q, char *base) @@ -455,6 +455,18 @@ static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) hdr->undoc = terminate; } +static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) +{ + make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); + hdr->undoc_buffer = len > 0 ? 1 : 0; +} + +static void make_unistr(UNISTR *str, char *buf) +{ + /* store the string (null-terminated copy) */ + PutUniCode((char *)(str->buffer), buf); +} + static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) { /* set up string lengths. add one if string is not null-terminated */ @@ -469,6 +481,16 @@ static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } +static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) +{ + int len_sid_str = strlen(sid_str); + + sid2->type = 0x5; + sid2->undoc = 0; + make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); + make_unistr (&(sid2->str), sid_str); +} + static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) { int domlen = strlen(dom_name); @@ -508,6 +530,79 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, return q - start; } +/* pretty much hard-coded choice of "other" sids, unfortunately... */ +static void make_dom_ref(DOM_R_REF *ref, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int len_dom_name = strlen(dom_name); + int len_other_sid1 = strlen(other_sid1); + int len_other_sid2 = strlen(other_sid2); + int len_other_sid3 = strlen(other_sid3); + + ref->undoc_buffer = 1; + ref->num_ref_doms_1 = 4; + ref->buffer_dom_name = 1; + ref->max_entries = 32; + ref->num_ref_doms_2 = 4; + + make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); + make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); + + if (dom_name != NULL) + { + make_unistr(&(ref->uni_dom_name), dom_name); + } + + make_dom_sid(&(ref->ref_dom[0]), dom_sid ); + make_dom_sid(&(ref->ref_dom[1]), other_sid1); + make_dom_sid(&(ref->ref_dom[2]), other_sid2); + make_dom_sid(&(ref->ref_dom[3]), other_sid3); +} + +static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + int num_entries, char *dom_sids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); + } + + r_l->num_entries3 = num_entries; +} + +static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + char *start = q; + LSA_R_LOOKUP_SIDS r_l; + + /* set up the LSA Lookup SIDs response */ + make_reply_lookup_sids(&r_l, 0, NULL, /* q_l->num_entries, q_l->dom_sids, */ + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); @@ -757,3 +852,44 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } + + +static void api_lsa_open_policy( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + /* we might actually want to decode the query, but it's not necessary */ + /* lsa_io_q_open_policy(...); */ + + /* return a 20 byte policy handle */ + reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + +static void api_lsa_query_info( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + LSA_Q_QUERY_INFO q_i; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + dom_name, dom_sid); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} -- cgit From 35dd48740d8f733e7725813322b094b4679b31c5 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 8 Oct 1997 18:36:34 +0000 Subject: added api_lsa_lookup_sids() function --- source/smbd/pipes.c | 1074 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1071 insertions(+), 3 deletions(-) diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 06b785bd873..88cf0b2d713 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -370,6 +370,29 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +char *dom_sid_to_string(DOM_SID *sid) +{ + static pstring sidstr; + char subauth[16]; + int i; + uint32 ia = (sid->id_auth[0]) + + (sid->id_auth[1] << 8 ) + + (sid->id_auth[2] << 16) + + (sid->id_auth[3] << 24); + + sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); + + for (i = 0; i < sid->num_auths; i++) + { + sprintf(subauth, "-%d", sid->sub_auths[i]); + strcat(sidstr, subauth); + } + + DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); + return sidstr; +} + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ /* identauth >= 2^32 can be detected because it will be specified in hex */ static void make_dom_sid(DOM_SID *sid, char *domsid) @@ -563,7 +586,7 @@ static void make_dom_ref(DOM_R_REF *ref, } static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - int num_entries, char *dom_sids[MAX_LOOKUP_SIDS], + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { @@ -584,7 +607,8 @@ static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, r_l->num_entries3 = num_entries; } -static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, +static int lsa_reply_lookup_sids(char *q, char *base, + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { @@ -592,7 +616,7 @@ static int lsa_reply_lookup_sids(LSA_Q_LOOKUP_SIDS *q_l, char *q, char *base, LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ - make_reply_lookup_sids(&r_l, 0, NULL, /* q_l->num_entries, q_l->dom_sids, */ + make_reply_lookup_sids(&r_l, num_entries, dom_sids, dom_name, dom_sid, other_sid1, other_sid2, other_sid3); r_l.status = 0x0; @@ -893,3 +917,1047 @@ static void api_lsa_query_info( char *param, char *data, make_rpc_reply(data, *rdata, reply_len); *rdata_len = reply_len + 0x18; } + +static void api_lsa_lookup_sids( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_LOOKUP_SIDS q_l; + pstring dom_name; + pstring dom_sid; + fstring dom_sids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received SIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + q_l.num_entries, dom_sids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + +BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + int nnames; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + DEBUG(4,("netlogon data %lx\n", data)); + q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +void initrpcreply(char *inbuf, char *q) +{ + uint32 callid; + + qSCVAL(5); /* RPC version 5 */ + qSCVAL(0); /* minor version 0 */ + qSCVAL(2); /* RPC response packet */ + qSCVAL(3); /* first frag + last frag */ + qRSIVAL(0x10000000); /* packed data representation */ + qRSSVAL(0); /* fragment length, fill in later */ + qSSVAL(0); /* authentication length */ + callid = RIVAL(inbuf,12); + qRSIVAL(callid); /* call identifier - match incoming RPC */ + qSIVAL(0x18); /* allocation hint (no idea) */ + qSSVAL(0); /* presentation context identifier */ + qSCVAL(0); /* cancel count */ + qSCVAL(0); /* reserved */ +} + +endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) +{ + SSVAL(q, 8, datalen + 4); + SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ + SIVAL(q, datalen, rtnval); + *rlen = datalen + 4; + {int fd; fd = open("/tmp/rpc", O_RDWR);write(fd,q,datalen+4);} +} + +void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + + +struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; + +int +nametorid(char *uniuser) +{ + if (!strncmp(unistr(uniuser+12),"ashtonp",7)) + return 2000; + if (!strncmp(unistr(uniuser+12),"user1",5)) + return 1; + if (!strncmp(unistr(uniuser+12),"user2",5)) + return 10; + if (!strncmp(unistr(uniuser+12),"user3",5)) + return 100; + return 3000; +} + +#endif /* NTDOMAIN */ -- cgit From b8ff5543b9fa45095caa9f24aeb22a1dcc1cd308 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Wed, 8 Oct 1997 20:34:13 +0000 Subject: Makefile: Split definitions for SGI4,5,6. includes.h: Split definitions for SGI4,5,6. pipes.c: Moved Luke's #ifdef to remove warnings. quotas.c: Two changes for FreeBSD and SGI. server.c: Quota changes for large filesystems. Jeremy (jallison@whistle.com) --- source/include/includes.h | 4 +- source/smbd/pipes.c | 2 +- source/smbd/quotas.c | 147 +++++++++++++++++++++++++++++++++++++++++++++- source/smbd/server.c | 20 ++++++- 4 files changed, 167 insertions(+), 6 deletions(-) diff --git a/source/include/includes.h b/source/include/includes.h index d1afc34de92..4ca1d4c3b0d 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -340,7 +340,7 @@ char *getwd(char *); #define USE_WAITPID #endif -#ifdef SGI +#ifdef SGI4 #include <netinet/tcp.h> #include <sys/statfs.h> #include <string.h> @@ -355,7 +355,7 @@ char *getwd(char *); #define USE_SETSID #endif -#ifdef SGI5 +#if defined(SGI5) || defined(SGI6) #include <arpa/inet.h> #include <netinet/tcp.h> #include <netinet/in_systm.h> diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 88cf0b2d713..870dc16fddf 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -364,6 +364,7 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } +#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -953,7 +954,6 @@ static void api_lsa_lookup_sids( char *param, char *data, } -#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index d4f746c9e36..8810bcd909d 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -416,10 +416,132 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } return (True); } + +#elif defined (SGI6) +/**************************************************************************** +try to get the disk space from disk quotas (IRIX 6.2 version) +****************************************************************************/ + +#include <sys/quota.h> +#include <mntent.h> + +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) +{ + uid_t euser_id; + int r; + struct dqblk D; + struct fs_disk_quota F; + struct stat S; + FILE *fp; + struct mntent *mnt; + int devno; + int found; + + /* find the block device file */ + + if ( stat(path, &S) == -1 ) { + return(False) ; + } + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + found = False ; + + while ((mnt = getmntent(fp))) { + if ( stat(mnt->mnt_dir,&S) == -1 ) + continue ; + if (S.st_dev == devno) { + found = True ; + break ; + } + } + endmntent(fp) ; + + if (!found) { + return(False); + } + + euser_id=geteuid(); + seteuid(0); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + + *bsize = 512; + + if ( 0 == strcmp ( mnt->mnt_type, "efs" )) + { + r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); + + if (r==-1) + return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || + (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || + (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) || + (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit) + ) + { + *dfree = 0; + *dsize = D.dqb_curblocks; + } + else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) + { + return(False); + } + else + { + *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; + *dsize = D.dqb_bsoftlimit; + } + + } + else if ( 0 == strcmp ( mnt->mnt_type, "xfs" )) + { + r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); + + if (r==-1) + return(False); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || + (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) || + (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) || + (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit) + ) + { + /* + * Fixme!: these are __uint64_t, this may truncate values + */ + *dfree = 0; + *dsize = (int) F.d_bcount; + } + else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) + { + return(False); + } + else + { + *dfree = (int)(F.d_blk_softlimit - F.d_bcount); + *dsize = (int)F.d_blk_softlimit; + } + + } + else + return(False); + + return (True); + +} + #else #ifdef __FreeBSD__ #include <ufs/ufs/quota.h> +#include <machine/param.h> #elif AIX /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ #include <jfs/quota.h> @@ -463,7 +585,25 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #else /* USE_SETRES */ #if defined(__FreeBSD__) - r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); + { + /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ + uid_t user_id; + gid_t egrp_id; + + /* Need to be root to get quotas in FreeBSD */ + user_id = getuid(); + egrp_id = getegid(); + setuid(0); + seteuid(0); + r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); + + /* As FreeBSD has group quotas, if getting the user + quota fails, try getting the group instead. */ + if (r) + r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); + setuid(user_id); + seteuid(euser_id); + } #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ @@ -474,7 +614,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ +#if defined(__FreeBSD__) + *bsize = DEV_BSIZE; +#else /* !__FreeBSD__ */ *bsize = 1024; +#endif /*!__FreeBSD__ */ + if (r) { if (errno == EDQUOT) diff --git a/source/smbd/server.c b/source/smbd/server.c index 290181fb9ee..2b906a76417 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -711,7 +711,15 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -801,7 +809,15 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; -- cgit From d7f41e3815babce58fa9901f076c2918666abaf9 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 8 Oct 1997 21:36:42 +0000 Subject: added a dummy function (space in front so make proto doesn't pick it up) to call the unused static functions in pipes.c. avoids need to move #if UNDEFINED_NTDOMAIN about, to stop compiler warnings while code is being developed, but might be released as-is. --- source/smbd/pipes.c | 1028 +-------------------------------------------------- 1 file changed, 20 insertions(+), 1008 deletions(-) diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 870dc16fddf..bedf847cc43 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -364,7 +364,6 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -#ifdef UNDEFINED_NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -953,1011 +952,24 @@ static void api_lsa_lookup_sids( char *param, char *data, *rdata_len = reply_len + 0x18; } - -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - int nnames; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - DEBUG(4,("netlogon data %lx\n", data)); - q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; - - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - } - return(True); -} - -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - } - return(True); +/* space in front of this function so that make proto doesn't pick it up */ + void _dummy_function(void) +{ + UTIME t; + lsa_reply_req_chal(NULL, NULL, NULL, NULL); + lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0); + lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0); + make_lsa_user_info(NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + 0, 0, + 0, 0, 0, NULL, 0, + NULL, + NULL, NULL, + NULL, NULL); + lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); + lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); + api_lsa_open_policy(NULL,NULL,NULL,NULL); + api_lsa_query_info(NULL,NULL,NULL,NULL); + api_lsa_lookup_sids(NULL,NULL,NULL,NULL); } - -void initrpcreply(char *inbuf, char *q) -{ - uint32 callid; - - qSCVAL(5); /* RPC version 5 */ - qSCVAL(0); /* minor version 0 */ - qSCVAL(2); /* RPC response packet */ - qSCVAL(3); /* first frag + last frag */ - qRSIVAL(0x10000000); /* packed data representation */ - qRSSVAL(0); /* fragment length, fill in later */ - qSSVAL(0); /* authentication length */ - callid = RIVAL(inbuf,12); - qRSIVAL(callid); /* call identifier - match incoming RPC */ - qSIVAL(0x18); /* allocation hint (no idea) */ - qSSVAL(0); /* presentation context identifier */ - qSCVAL(0); /* cancel count */ - qSCVAL(0); /* reserved */ -} - -endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) -{ - SSVAL(q, 8, datalen + 4); - SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ - SIVAL(q, datalen, rtnval); - *rlen = datalen + 4; - {int fd; fd = open("/tmp/rpc", O_RDWR);write(fd,q,datalen+4);} -} - -void setsesskey(int cnum) -{ - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); -} - -void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} - -void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} - - -struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; - -int -nametorid(char *uniuser) -{ - if (!strncmp(unistr(uniuser+12),"ashtonp",7)) - return 2000; - if (!strncmp(unistr(uniuser+12),"user1",5)) - return 1; - if (!strncmp(unistr(uniuser+12),"user2",5)) - return 10; - if (!strncmp(unistr(uniuser+12),"user3",5)) - return 100; - return 3000; -} - -#endif /* NTDOMAIN */ -- cgit From fa69b3dda47d56e0c3ce1f4f284eac89d4b4bf56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Wed, 8 Oct 1997 22:23:47 +0000 Subject: Put in fix for read-prediction extending files bug. Hard to test, can't get read-prediction to happen :-). Jeremy (jallison@whistle.com) --- source/smbd/predict.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/source/smbd/predict.c b/source/smbd/predict.c index 691d8fbb4e0..7d6b2498f5a 100644 --- a/source/smbd/predict.c +++ b/source/smbd/predict.c @@ -53,24 +53,37 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) offset >= rp_offset && possible>0 && smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } if (ret == num) { predict_skip = True; } else { - predict_skip = False; + struct stat rp_stat; + + /* Find the end of the file - ensure we don't + read predict beyond it. */ + if(fstat(fd,&rp_stat) < 0) + { + DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); + predict_skip = True; + } + else + { + predict_skip = False; - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; + /* prepare the next prediction */ + rp_predict_fd = fd; + /* Make sure we don't seek beyond the end of the file. */ + rp_predict_offset = MIN((offset + num),rp_stat.st_size); + rp_predict_length = num; + } } if (ret < 0) ret = 0; -- cgit From 2614cd1d35ab53e952e5bcfbb1d50b0feeefeeb6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Thu, 9 Oct 1997 00:43:55 +0000 Subject: predict.c: stop lseek from extending file. Hard to test. proto.h: updated. quotas.c: Added FreeBSD fixes. server.c: Added quota overflow fix for large filesystems. Rolled back to old error codes. Jeremy (jallison@whistle.com) --- source/smbd/predict.c | 39 ++++++++++++++++++++++++++------------- source/smbd/quotas.c | 27 ++++++++++++++++++++++++++- source/smbd/server.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/source/smbd/predict.c b/source/smbd/predict.c index 691d8fbb4e0..7d6b2498f5a 100644 --- a/source/smbd/predict.c +++ b/source/smbd/predict.c @@ -53,24 +53,37 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) offset >= rp_offset && possible>0 && smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } if (ret == num) { predict_skip = True; } else { - predict_skip = False; + struct stat rp_stat; + + /* Find the end of the file - ensure we don't + read predict beyond it. */ + if(fstat(fd,&rp_stat) < 0) + { + DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); + predict_skip = True; + } + else + { + predict_skip = False; - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; + /* prepare the next prediction */ + rp_predict_fd = fd; + /* Make sure we don't seek beyond the end of the file. */ + rp_predict_offset = MIN((offset + num),rp_stat.st_size); + rp_predict_length = num; + } } if (ret < 0) ret = 0; diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index d4f746c9e36..2d238dfaf17 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -416,10 +416,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } return (True); } + #else #ifdef __FreeBSD__ #include <ufs/ufs/quota.h> +#include <machine/param.h> #elif AIX /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ #include <jfs/quota.h> @@ -463,7 +465,25 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #else /* USE_SETRES */ #if defined(__FreeBSD__) - r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); + { + /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ + uid_t user_id; + gid_t egrp_id; + + /* Need to be root to get quotas in FreeBSD */ + user_id = getuid(); + egrp_id = getegid(); + setuid(0); + seteuid(0); + r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); + + /* As FreeBSD has group quotas, if getting the user + quota fails, try getting the group instead. */ + if (r) + r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); + setuid(user_id); + seteuid(euser_id); + } #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ @@ -474,7 +494,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ +#if defined(__FreeBSD__) + *bsize = DEV_BSIZE; +#else /* !__FreeBSD__ */ *bsize = 1024; +#endif /*!__FreeBSD__ */ + if (r) { if (errno == EDQUOT) diff --git a/source/smbd/server.c b/source/smbd/server.c index 35a7c730be4..8e1bc152ffd 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -703,7 +703,15 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -793,7 +801,15 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -1963,7 +1979,11 @@ struct {EPERM,ERRDOS,ERRnoaccess}, {EACCES,ERRDOS,ERRnoaccess}, {ENOENT,ERRDOS,ERRbadfile}, +#if 0 /* Go back to old method for now. */ {ENOTDIR,ERRDOS,ERRbaddirectory}, +#else + {ENOTDIR,ERRDOS,ERRbadpath}, +#endif {EIO,ERRHRD,ERRgeneral}, {EBADF,ERRSRV,ERRsrverror}, {EINVAL,ERRSRV,ERRsrverror}, @@ -1984,6 +2004,7 @@ struct {0,0,0} }; +#if 0 /* Go back to old method for now. */ /* Mapping for old clients. */ struct @@ -1998,6 +2019,8 @@ struct {0,0,0} }; +#endif /* Go back to old method for now. */ + /**************************************************************************** create an error packet from errno ****************************************************************************/ @@ -2028,6 +2051,8 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int } } +#if 0 /* Go back to old method for now. */ + /* Make sure we don't return error codes that old clients don't understand. */ @@ -2050,6 +2075,7 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int break; } } +#endif /* Go back to old method for now. */ return(error_packet(inbuf,outbuf,eclass,ecode,line)); } -- cgit From e789179dfda669bd768720cb3732cf56a49027b5 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 9 Oct 1997 04:09:56 +0000 Subject: This is my library of lists and trees. My hope is to replace all of the hard coded linked lists that are currently used in Samba with calls to these modules. This should make the code simpler, smaller, and (I hope) faster. The tree code, in particular, should speed up processing where large lists are involved. Chris -)----- --- source/ubi_AVLtree.c | 699 ++++++++++++++++++++++++++++++++ source/ubi_AVLtree.h | 340 ++++++++++++++++ source/ubi_BinTree.c | 1042 ++++++++++++++++++++++++++++++++++++++++++++++++ source/ubi_BinTree.h | 745 ++++++++++++++++++++++++++++++++++ source/ubi_SplayTree.c | 472 ++++++++++++++++++++++ source/ubi_SplayTree.h | 339 ++++++++++++++++ source/ubi_dLinkList.c | 152 +++++++ source/ubi_dLinkList.h | 163 ++++++++ 8 files changed, 3952 insertions(+) create mode 100644 source/ubi_AVLtree.c create mode 100644 source/ubi_AVLtree.h create mode 100644 source/ubi_BinTree.c create mode 100644 source/ubi_BinTree.h create mode 100644 source/ubi_SplayTree.c create mode 100644 source/ubi_SplayTree.h create mode 100644 source/ubi_dLinkList.c create mode 100644 source/ubi_dLinkList.h diff --git a/source/ubi_AVLtree.c b/source/ubi_AVLtree.c new file mode 100644 index 00000000000..730392a472a --- /dev/null +++ b/source/ubi_AVLtree.c @@ -0,0 +1,699 @@ +/* ========================================================================== ** + * ubi_AVLtree.c + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This file implements the core of the height-balanced (AVL) tree management + * routines. The header file, ubi_AVLtree.h, contains function prototypes + * for all "exported" functions. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_AVLtree.c,v $ + * Revision 1.1 1997/10/09 04:09:51 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.4 1997/07/26 04:36:20 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 04:41:35 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:16:01 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:45:59 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:10:51 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:56 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "ubi_AVLtree.h" /* Header for THIS module. */ +#include <stdlib.h> /* Standard C definitions, etc. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_AVLtree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/09 04:09:51 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * The next set of functions are the AVL balancing routines. There are left + * and right, single and double rotations. The rotation routines handle the + * rotations and reconnect all tree pointers that might get confused by the + * rotations. A pointer to the new subtree root node is returned. + * + * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs + * are reversed. The same is true for L2 and R2. I'm sure that there is + * a clever way to reduce the amount of code by combining these functions, + * but it might involve additional overhead, and it would probably be a pain + * to read, debug, etc. + * -------------------------------------------------------------------------- ** + */ + +static ubi_avlNodePtr L1( ubi_avlNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp; + + tmp = p->Link[RIGHT]; + p->Link[RIGHT] = tmp->Link[LEFT]; + tmp->Link[LEFT] = p; + + tmp->Link[PARENT] = p->Link[PARENT]; + tmp->gender = p->gender; + if(tmp->Link[PARENT]) + (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; + p->Link[PARENT] = tmp; + p->gender = LEFT; + if( p->Link[RIGHT] ) + { + p->Link[RIGHT]->Link[PARENT] = p; + (p->Link[RIGHT])->gender = RIGHT; + } + p->balance -= Normalize( tmp->balance ); + (tmp->balance)--; + return( tmp ); + } /* L1 */ + +static ubi_avlNodePtr R1( ubi_avlNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp; + + tmp = p->Link[LEFT]; + p->Link[LEFT] = tmp->Link[RIGHT]; + tmp->Link[RIGHT] = p; + + tmp->Link[PARENT] = p->Link[PARENT]; + tmp->gender = p->gender; + if(tmp->Link[PARENT]) + (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; + p->Link[PARENT] = tmp; + p->gender = RIGHT; + if(p->Link[LEFT]) + { + p->Link[LEFT]->Link[PARENT] = p; + p->Link[LEFT]->gender = LEFT; + } + p->balance -= Normalize( tmp->balance ); + (tmp->balance)++; + return( tmp ); + } /* R1 */ + +static ubi_avlNodePtr L2( ubi_avlNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp, newroot; + + tmp = tree->Link[RIGHT]; + newroot = tmp->Link[LEFT]; + tmp->Link[LEFT] = newroot->Link[RIGHT]; + newroot->Link[RIGHT] = tmp; + tree->Link[RIGHT] = newroot->Link[LEFT]; + newroot->Link[LEFT] = tree; + + newroot->Link[PARENT] = tree->Link[PARENT]; + newroot->gender = tree->gender; + tree->Link[PARENT] = newroot; + tree->gender = LEFT; + tmp->Link[PARENT] = newroot; + tmp->gender = RIGHT; + + if( tree->Link[RIGHT] ) + { + tree->Link[RIGHT]->Link[PARENT] = tree; + tree->Link[RIGHT]->gender = RIGHT; + } + if( tmp->Link[LEFT] ) + { + tmp->Link[LEFT]->Link[PARENT] = tmp; + tmp->Link[LEFT]->gender = LEFT; + } + if(newroot->Link[PARENT]) + newroot->Link[PARENT]->Link[newroot->gender] = newroot; + + switch( newroot->balance ) + { + case LEFT : + tree->balance = EQUAL; tmp->balance = RIGHT; break; + case EQUAL: + tree->balance = EQUAL; tmp->balance = EQUAL; break; + case RIGHT: + tree->balance = LEFT; tmp->balance = EQUAL; break; + } + newroot->balance = EQUAL; + return( newroot ); + } /* L2 */ + +static ubi_avlNodePtr R2( ubi_avlNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp, newroot; + + tmp = tree->Link[LEFT]; + newroot = tmp->Link[RIGHT]; + tmp->Link[RIGHT] = newroot->Link[LEFT]; + newroot->Link[LEFT] = tmp; + tree->Link[LEFT] = newroot->Link[RIGHT]; + newroot->Link[RIGHT] = tree; + + newroot->Link[PARENT] = tree->Link[PARENT]; + newroot->gender = tree->gender; + tree->Link[PARENT] = newroot; + tree->gender = RIGHT; + tmp->Link[PARENT] = newroot; + tmp->gender = LEFT; + + if( tree->Link[LEFT] ) + { + tree->Link[LEFT]->Link[PARENT] = tree; + tree->Link[LEFT]->gender = LEFT; + } + if( tmp->Link[RIGHT] ) + { + tmp->Link[RIGHT]->Link[PARENT] = tmp; + tmp->Link[RIGHT]->gender = RIGHT; + } + if(newroot->Link[PARENT]) + newroot->Link[PARENT]->Link[newroot->gender] = newroot; + + switch( newroot->balance ) + { + case LEFT : + tree->balance = RIGHT; tmp->balance = EQUAL; break; + case EQUAL : + tree->balance = EQUAL; tmp->balance = EQUAL; break; + case RIGHT : + tree->balance = EQUAL; tmp->balance = LEFT; break; + } + newroot->balance = EQUAL; + return( newroot ); + } /* R2 */ + + +static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR ) + /* ------------------------------------------------------------------------ ** + * Adjust the balance value at node *p. If necessary, rotate the subtree + * rooted at p. + * + * Input: p - A pointer to the node to be adjusted. One of the + * subtrees of this node has changed height, so the + * balance value at this node must be adjusted, possibly + * by rotating the tree at this node. + * LorR - Indicates the TALLER subtree. + * + * Output: A pointer to the (possibly new) root node of the subtree. + * + * Notes: This function may be called after a node has been added *or* + * deleted, so LorR indicates the TALLER subtree. + * ------------------------------------------------------------------------ ** + */ + { + if( p->balance != LorR ) + p->balance += Normalize(LorR); + else + { + char tallerbal; /* Balance value of the root of the taller subtree of p. */ + + tallerbal = p->Link[LorR]->balance; + if( ( EQUAL == tallerbal ) || ( p->balance == tallerbal ) ) + p = ( (LEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */ + else + p = ( (LEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */ + } + return( p ); + } /* Adjust */ + +static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root, + ubi_avlNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following an insertion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node that has just gained a new + * child. + * LorR - Gender of the child that has just been gained. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Rebalance() must walk up the tree from where we are (which is + * where the latest change occurred), rebalancing the subtrees + * along the way. The rebalancing operation can stop if the + * change at the current subtree root won't affect the rest of + * the tree. In the case of an addition, if a subtree root's + * balance becomes EQUAL, then we know that the height of that + * subtree has not changed, so we can exit. + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, LorR ); + if( PARENT == subtree->gender ) + return( subtree ); + if( EQUAL == subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[PARENT]; + } + return( Root ); + } /* Rebalance */ + +static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root, + ubi_avlNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following a deletion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node who's child has just "left the + * nest". + * LorR - Gender of the child that left. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Debalance() is subtly different from Rebalance() (above) in + * two respects. + * * When it calls Adjust(), it passes the *opposite* of LorR. + * This is because LorR, as passed into Debalance() indicates + * the shorter subtree. As we move up the tree, LorR is + * assigned the gender of the node that we are leaving (i.e., + * the subtree that we just rebalanced). + * * We know that a subtree has not changed height if the + * balance becomes LEFT or RIGHT. This is the *opposite* of + * what happens in Rebalance(). + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, RevWay(LorR) ); + if( PARENT == subtree->gender ) + return( subtree ); + if( EQUAL != subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[PARENT]; + } + return( Root ); + } /* Debalance */ + + +/* -------------------------------------------------------------------------- ** + * The next two functions are used for general tree manipulation. They are + * each slightly different from their ubi_BinTree counterparts. + * -------------------------------------------------------------------------- ** + */ + +static void ReplaceNode( ubi_avlNodePtr *parent, + ubi_avlNodePtr oldnode, + ubi_avlNodePtr newnode ) + /* ------------------------------------------------------------------------ ** + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. <parent> may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * The only difference between this function and the ubi_bt + * version is that the node size is sizeof( ubi_avlNode ), not + * sizeof( ubi_btNode ). + * ------------------------------------------------------------------------ ** + */ + { + register int i; + register int avlNodeSize = sizeof( ubi_avlNode ); + + for( i = 0; i < avlNodeSize; i++ ) + ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + (*parent) = newnode; + + if(oldnode->Link[LEFT ] ) + (oldnode->Link[LEFT ])->Link[PARENT] = newnode; + if(oldnode->Link[RIGHT] ) + (oldnode->Link[RIGHT])->Link[PARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_avlNodePtr Node1, + ubi_avlNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_avlRemove(). + * The only difference between this function and its ubi_bt counterpart + * is that the nodes are ubi_avlNodes, not ubi_btNodes. + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr *Parent; + ubi_avlNode dummy; + ubi_avlNodePtr dummy_p = &dummy; + + if( Node1->Link[PARENT] ) + Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + if( Node2->Link[PARENT] ) + Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + if( dummy_p->Link[PARENT] ) + Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + + +/* ========================================================================== ** + * Public, exported (ie. not static-ly declared) functions... + * -------------------------------------------------------------------------- ** + */ + +ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: NodePtr - pointer to a ubi_btNode structure to be + * initialized. + * Output: a pointer to the initialized ubi_avlNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + (void)ubi_btInitNode( (ubi_btNodePtr)NodePtr ); + NodePtr->balance = EQUAL; + return( NodePtr ); + } /* ubi_avlInitNode */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_avlNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_avlNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_avlNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr OtherP; + + if( !(OldNode) ) OldNode = &OtherP; + if( ubi_btInsert( RootPtr, + (ubi_btNodePtr)NewNode, + ItemPtr, + (ubi_btNodePtr *)OldNode ) ) + { + if( (*OldNode) ) + NewNode->balance = (*OldNode)->balance; + else + { + NewNode->balance = EQUAL; + RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_avlNodePtr)RootPtr->root, + NewNode->Link[PARENT], + NewNode->gender ); + } + return( ubi_trTRUE ); + } + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_avlInsert */ + +ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_avlNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. + */ + if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_trPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if( DeadNode->Link[PARENT] ) + parentp = (ubi_btNodePtr *) + &((DeadNode->Link[PARENT])->Link[(DeadNode->gender)]); + else + parentp = &( RootPtr->root ); + + /* Now link the parent to the only grand-child. Patch up the gender and + * such, and rebalance. + */ + if( EQUAL == DeadNode->balance ) + (*parentp) = NULL; + else + { + p = (ubi_btNodePtr)(DeadNode->Link[(DeadNode->balance)]); + p->Link[PARENT] = (ubi_btNodePtr)DeadNode->Link[PARENT]; + p->gender = DeadNode->gender; + (*parentp) = p; + } + RootPtr->root = (ubi_btNodePtr)Debalance( (ubi_avlNodePtr)RootPtr->root, + DeadNode->Link[PARENT], + DeadNode->gender ); + + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_avlRemove */ + +int ubi_avlModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_avlModuleID */ + +/* ============================== The End ============================== */ diff --git a/source/ubi_AVLtree.h b/source/ubi_AVLtree.h new file mode 100644 index 00000000000..27d84a2896d --- /dev/null +++ b/source/ubi_AVLtree.h @@ -0,0 +1,340 @@ +#ifndef ubi_AVLtree_H +#define ubi_AVLtree_H +/* ========================================================================== ** + * ubi_AVLtree.h + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This header file contains the basic AVL structure and pointer typedefs + * as well as the prototypes needed to access the functions in the AVL + * module ubi_AVLtree. The .c file implements the low-level height balancing + * routines that manage the AVL tree, plus all of the basic primops for + * adding, searching for, and deleting nodes. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * $Log: ubi_AVLtree.h,v $ + * Revision 1.1 1997/10/09 04:09:51 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.4 1997/07/26 04:36:23 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 05:22:07 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:15:47 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:46:44 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:11:22 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:48 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "ubi_BinTree.h" /* Base erg binary tree support. */ + +/* ------------------------------------------------------------------------- ** + * AVL Tree Node Structure: This structure defines the basic elements of + * the AVL tree nodes. In general you *SHOULD NOT PLAY WITH THESE + * FIELDS*! But, of course, I have to put the structure into this + * header so that you can use the structure as a building block. + * + * The fields are as follows: + * Link - An array of pointers. These pointers are manipulated by the + * BT and AVL routines, and indicate the left and right child + * nodes, plus the parent node. By keeping track of the parent + * pointer, we avoid the need for recursive routines or hand- + * tooled stacks to keep track of our path back to the root. + * The use of these pointers is subject to change without + * notice. + * gender - For tree rebalancing purposes, it is necessary that each node + * know whether it is the left or right child of its parent, or + * if it is the root. This information is stored in this field. + * balance - This field is also needed for AVL balancing purposes. It + * indicates which subtree of the current node is longer, or if + * the subtrees are, in fact, balanced with respect to each + * other. + * ------------------------------------------------------------------------- ** + */ + +typedef struct ubi_avlNodeStruct { + struct ubi_avlNodeStruct + *Link[3]; /* Normal Binary Tree Node type. */ + char gender; /* The node is either the RIGHT or LEFT child of its */ + /* parent, or is the root node. */ + char balance; /* In an AVL tree, each node is the root of a subtree */ + /* that may be balanced, or be one node longer to the */ + /* right or left. This field keeps track of the */ + /* balance value of each node. */ + } ubi_avlNode; /* Typedef'd name for an avl tree node. */ + +typedef ubi_avlNode *ubi_avlNodePtr; /* a Pointer to an AVL node */ + +/* -------------------------------------------------------------------------- ** + * Function prototypes. + * -------------------------------------------------------------------------- ** + */ + +ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: NodePtr - a pointer to a ubi_btNode structure to be + * initialized. + * Output: a pointer to the initialized ubi_avlNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_avlNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_avlNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_avlNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_avlNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +int ubi_avlModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_avl... or ubi_bt, use ubi_tr... and select the tree + * type by including the appropriate module header. + */ + +#undef ubi_trNode +#undef ubi_trNodePtr +#define ubi_trNode ubi_avlNode +#define ubi_trNodePtr ubi_avlNodePtr + +#undef ubi_trInitNode +#define ubi_trInitNode( Np ) ubi_avlInitNode( (ubi_avlNodePtr)(Np) ) + +#undef ubi_trInsert +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_avlNodePtr *)(On) ) + +#undef ubi_trRemove +#define ubi_trRemove( Rp, Dn ) \ + ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Dn) ) + +#undef ubi_trLocate +#define ubi_trLocate( Rp, Ip, Op ) \ + (ubi_avlNodePtr)ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#undef ubi_trFind +#define ubi_trFind( Rp, Ip ) \ + (ubi_avlNodePtr)ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#undef ubi_trNext +#define ubi_trNext( P ) (ubi_avlNodePtr)ubi_btNext( (ubi_btNodePtr)(P) ) + +#undef ubi_trPrev +#define ubi_trPrev( P ) (ubi_avlNodePtr)ubi_btPrev( (ubi_btNodePtr)(P) ) + +#undef ubi_trFirst +#define ubi_trFirst( P ) (ubi_avlNodePtr)ubi_btFirst( (ubi_btNodePtr)(P) ) + +#undef ubi_trLast +#define ubi_trLast( P ) (ubi_avlNodePtr)ubi_btLast( (ubi_btNodePtr)(P) ) + +#undef ubi_trFirstOf +#define ubi_trFirstOf( Rp, Ip, P ) \ + (ubi_avlNodePtr)ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#undef ubi_trLastOf +#define ubi_trLastOf( Rp, Ip, P ) \ + (ubi_avlNodePtr)ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#undef ubi_trLeafNode +#define ubi_trLeafNode( Nd ) \ + (ubi_avlNodePtr)ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#undef ubi_trModuleID +#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l ) + + +/* =========================== End ubi_AVLtree.h =========================== */ +#endif /* ubi_AVLtree_H */ diff --git a/source/ubi_BinTree.c b/source/ubi_BinTree.c new file mode 100644 index 00000000000..e6db1a4816c --- /dev/null +++ b/source/ubi_BinTree.c @@ -0,0 +1,1042 @@ +/* ========================================================================== ** + * ubi_BinTree.c + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height + * balancing, no restructuring. Still, a good tool for creating short, low- + * overhead sorted lists of things that need to be found in a hurry. + * + * In addition, this module provides a good basis for creating other types + * of binary tree handling modules. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.c,v $ + * Revision 1.1 1997/10/09 04:09:52 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.4 1997/07/26 04:11:10 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:16:17 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:07 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:37:10 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:17 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:44:59 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Header for this module */ +#include <stdlib.h> /* Standard C definitions. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_BinTree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/09 04:09:52 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * Internal (private) functions. + */ + +static ubi_btNodePtr qFind( ubi_btCompFunc cmp, + ubi_btItemPtr FindMe, + register ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for a node + * matching a specific key. It is called "qFind()" because it is + * faster that TreeFind (below). + * + * Input: + * cmp - a pointer to the tree's comparison function. + * FindMe - a pointer to the key value for which to search. + * p - a pointer to the starting point of the search. <p> + * is considered to be the root of a subtree, and only + * the subtree will be searched. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. + * ------------------------------------------------------------------------ ** + */ + { + char tmp; + + while( p && (( tmp = AbNormal((*cmp)(FindMe, p)) ) != EQUAL) ) + p = p->Link[tmp]; + + return( p ); + } /* qFind */ + +static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, + ubi_btNodePtr p, + ubi_btNodePtr *parentp, + char *gender, + ubi_btCompFunc CmpFunc ) + /* ------------------------------------------------------------------------ ** + * TreeFind() searches a tree for a given value (findme). It will return a + * pointer to the target node, if found, or NULL if the target node was not + * found. + * + * TreeFind() also returns, via parameters, a pointer to the parent of the + * target node, and a LEFT or RIGHT value indicating which child of the + * parent is the target node. *If the target is not found*, then these + * values indicate the place at which the target *should be found*. This + * is useful when inserting a new node into a tree or searching for nodes + * "near" the target node. + * + * The parameters are: + * + * findme - is a pointer to the key information to be searched for. + * p - points to the root of the tree to be searched. + * parentp - will return a pointer to a pointer to the !parent! of the + * target node, which can be especially usefull if the target + * was not found. + * gender - returns LEFT or RIGHT to indicate which child of *parentp + * was last searched. + * CmpFunc - points to the comparison function. + * + * This function is called by ubi_btLocate() and ubi_btInsert(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr tmp_p = p; + ubi_btNodePtr tmp_pp = NULL; + char tmp_sex = EQUAL; + char tmp_cmp; + + while( tmp_p && (EQUAL != (tmp_cmp = AbNormal((*CmpFunc)(findme, tmp_p)))) ) + { + tmp_pp = tmp_p; /* Keep track of previous node. */ + tmp_sex = tmp_cmp; /* Keep track of sex of child. */ + tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ + } + *parentp = tmp_pp; /* Return results. */ + *gender = tmp_sex; + return( tmp_p ); + } /* TreeFind */ + +static void ReplaceNode( ubi_btNodePtr *parent, + ubi_btNodePtr oldnode, + ubi_btNodePtr newnode ) + /* ------------------------------------------------------------------ * + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. <parent> may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * Also, this function used to have a really nasty typo + * bug. "oldnode" and "newnode" were swapped in the line + * that now reads: + * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + * Bleah! + * ------------------------------------------------------------------ * + */ + { + register int i; + register int btNodeSize = sizeof( ubi_btNode ); + + for( i = 0; i < btNodeSize; i++ ) /* Copy node internals to new node. */ + ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + (*parent) = newnode; /* Old node's parent points to new child. */ + /* Now tell the children about their new step-parent. */ + if( oldnode->Link[LEFT ] ) (oldnode->Link[LEFT ])->Link[PARENT] = newnode; + if( oldnode->Link[RIGHT] ) (oldnode->Link[RIGHT])->Link[PARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_btNodePtr Node1, + ubi_btNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_btRemove(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr *Parent; + ubi_btNode dummy; + ubi_btNodePtr dummy_p = &dummy; + + /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ + if( Node1->Link[PARENT] ) + Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ + if( Node2->Link[PARENT] ) + Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ + if( dummy_p->Link[PARENT] ) + Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + +/* -------------------------------------------------------------------------- ** + * These routines allow you to walk through the tree, forwards or backwards. + */ + +static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, + register char whichway ) + /* ------------------------------------------------------------------------ ** + * Slide down the side of a subtree. + * + * Given a starting node, this function returns a pointer to the LEFT-, or + * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. + * + * Input: P - a pointer to a starting place. + * whichway - the direction (LEFT, RIGHT, or PARENT) in which to + * travel. + * Output: A pointer to a node that is either the root, or has no + * whichway-th child but is within the subtree of P. Note that + * the return value may be the same as P. The return value *will + * be* NULL if P is NULL. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr Q = NULL; + + while( P ) + { + Q = P; + P = P->Link[ whichway ]; + } + return( Q ); + } /* SubSlide */ + +static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, + register char whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, return the (key order) next or preceeding node + * in the tree. + * + * Input: P - Pointer to our starting place node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the neighboring node, or NULL if P was NULL. + * + * Notes: If whichway is PARENT, the results are unpredictable. + * ------------------------------------------------------------------------ ** + */ + { + if( P ) + { + if( P->Link[ whichway ] ) + return( SubSlide( P->Link[ whichway ], (char)RevWay(whichway) ) ); + else + while( P->Link[ PARENT ] ) + { + if( (P->Link[ PARENT ])->Link[ whichway ] == P ) + P = P->Link[ PARENT ]; + else + return( P->Link[ PARENT ] ); + } + } + return( NULL ); + } /* Neighbor */ + +static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_btNodePtr p, + char whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, which has a key value equal to *FindMe, locate + * the first (index order) node with the same key value. + * + * This function is useful in trees that have can have duplicate keys. + * For example, consider the following tree: + * Tree Traversal + * 2 If <p> points to the root and <whichway> is RIGHT, 3 + * / \ then the return value will be a pointer to the / \ + * 2 2 RIGHT child of the root node. The tree on 2 5 + * / / \ the right shows the order of traversal. / / \ + * 1 2 3 1 4 6 + * + * Input: RootPtr - Pointer to the tree root structure. + * FindMe - Key value for comparisons. + * p - Pointer to the starting-point node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the first (index, or "traversal", order) node with + * a Key value that matches *FindMe. + * + * Notes: If whichway is PARENT, or if the tree does not allow duplicate + * keys, this function will return <p>. + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr q; + + /* Exit if there's nothing that can be done. */ + if( !Dups_OK( RootPtr ) || (PARENT == whichway) ) + return( p ); + + /* First, if needed, move up the tree. We need to get to the root of the + * subtree that contains all of the matching nodes. + */ + q = p->Link[PARENT]; + while( q && (EQUAL == AbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) + { + p = q; + q = p->Link[PARENT]; + } + + /* Next, move back down in the "whichway" direction. */ + q = p->Link[whichway]; + while( q ) + { + if( q = qFind( RootPtr->cmp, FindMe, q ) ) + { + p = q; + q = p->Link[whichway]; + } + } + return( p ); + } /* Border */ + + +/* ========================================================================== ** + * Exported utilities. + */ + +long ubi_btSgn( register long x ) + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + { + return( (x)?((x>0)?(1):(-1)):(0) ); + } /* ubi_btSgn */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + NodePtr->Link[ LEFT ] = NULL; + NodePtr->Link[ PARENT ] = NULL; + NodePtr->Link[ RIGHT ] = NULL; + NodePtr->gender = EQUAL; + return( NodePtr ); + } /* ubi_btInitNode */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + unsigned char Flags ) + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * + * ------------------------------------------------------------------------ ** + */ + { + if( RootPtr ) + { + RootPtr->root = NULL; + RootPtr->count = 0L; + RootPtr->cmp = CompFunc; + RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; + } /* There are only two supported flags, and they are + * mutually exclusive. ubi_trDUPKEY takes precedence + * over ubi_trOVERWRITE. + */ + return( RootPtr ); + } /* ubi_btInitTree */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP, + parent = NULL; + char tmp; + + if( !(OldNode) ) /* If they didn't give us a pointer, supply our own. */ + OldNode = &OtherP; + + (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ + + /* Find a place for the new node. */ + *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); + + /* Now add the node to the tree... */ + if (!(*OldNode)) /* The easy one: we have a space for a new node! */ + { + if (!(parent)) + RootPtr->root = NewNode; + else + { + parent->Link[tmp] = NewNode; + NewNode->Link[PARENT] = parent; + NewNode->gender = tmp; + } + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we reach this point, we know that a duplicate node exists. This + * section adds the node to the tree if duplicate keys are allowed. + */ + if( Dups_OK(RootPtr) ) /* Key exists, add duplicate */ + { + ubi_btNodePtr q; + + tmp = RIGHT; + q = (*OldNode); + *OldNode = NULL; + while( q ) + { + parent = q; + if( tmp == EQUAL ) tmp = RIGHT; + q = q->Link[tmp]; + if ( q ) + tmp = AbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); + } + parent->Link[tmp] = NewNode; + NewNode->Link[PARENT] = parent; + NewNode->gender = tmp; + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we get to *this* point, we know that we are not allowed to have + * duplicate nodes, but our node keys match, so... may we replace the + * old one? + */ + if( Ovwt_OK(RootPtr) ) /* Key exists, we replace */ + { + if (!(parent)) + ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); + else + ReplaceNode( &(parent->Link[(*OldNode)->gender]), *OldNode, NewNode ); + return( ubi_trTRUE ); + } + + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_btInsert */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + char tmp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. The other node we choose will be the Prev()ious + * node, which is garunteed to have no RIGHT child. + */ + if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if (DeadNode->Link[PARENT]) + parentp = &((DeadNode->Link[PARENT])->Link[DeadNode->gender]); + else + parentp = &( RootPtr->root ); + + /* Now link the parent to the only grand-child and patch up the gender. */ + tmp = ((DeadNode->Link[LEFT])?LEFT:RIGHT); + + p = (DeadNode->Link[tmp]); + if( p ) + { + p->Link[PARENT] = DeadNode->Link[PARENT]; + p->gender = DeadNode->gender; + } + (*parentp) = p; + + /* Finished, reduce the node count and return. */ + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_btRemove */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr p; + ubi_btNodePtr parent; + char whichkid; + + /* Start by searching for a matching node. */ + p = TreeFind( FindMe, + RootPtr->root, + &parent, + &whichkid, + RootPtr->cmp ); + + if( p ) /* If we have found a match, we can resolve as follows: */ + { + switch( CompOp ) + { + case ubi_trLT: /* It's just a jump to the left... */ + p = Border( RootPtr, FindMe, p, LEFT ); + return( Neighbor( p, LEFT ) ); + case ubi_trGT: /* ...and then a jump to the right. */ + p = Border( RootPtr, FindMe, p, RIGHT ); + return( Neighbor( p, RIGHT ) ); + } + p = Border( RootPtr, FindMe, p, LEFT ); + return( p ); + } + + /* Else, no match. */ + if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ + return( NULL ); /* ...forget it. */ + + /* We can still return a valid result for GT, GE, LE, and LT. + * <parent> points to a node with a value that is either just before or + * just after the target value. + * Remaining possibilities are LT and GT (including LE & GE). + */ + if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) + return( (LEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + else + return( (RIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + } /* ubi_btLocate */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + { + return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); + } /* ubi_btFind */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, RIGHT ) ); + } /* ubi_btNext */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, LEFT ) ); + } /* ubi_btPrev */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, LEFT ) ); + } /* ubi_btFirst */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, RIGHT ) ); + } /* ubi_btLast */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, LEFT ) ); + } /* ubi_btFirstOf */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, RIGHT ) ); + } /* ubi_btLastOf */ + +ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ) + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + if( !(p = ubi_btFirst( RootPtr->root )) ) return( ubi_trFALSE ); + + while( p ) + { + EachNode( p, UserData ); + p = ubi_btNext( p ); + } + return( ubi_trTRUE ); + } /* ubi_btTraverse */ + +ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ) + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Note that this function will return FALSE if either parameter + * is NULL. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: A boolean value. FALSE if either input parameter was NULL, else + * TRUE. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, q; + + if( !(RootPtr) || !(FreeNode) ) + return( ubi_trFALSE ); + + p = ubi_btFirst( RootPtr->root ); + while( p ) + { + q = p; + while( q->Link[RIGHT] ) + q = SubSlide( q->Link[RIGHT], LEFT ); + p = q->Link[PARENT]; + if( p ) + p->Link[ ((p->Link[LEFT] == q)?LEFT:RIGHT) ] = NULL; + FreeNode((void *)q); + } + + (void)ubi_btInitTree( RootPtr, + RootPtr->cmp, + RootPtr->flags ); + return( ubi_trTRUE ); + } /* ubi_btKillTree */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr follower = NULL; + int whichway = LEFT; + + while( NULL != leader ) + { + follower = leader; + leader = follower->Link[ whichway ]; + if( NULL == leader ) + { + whichway = RevWay( whichway ); + leader = follower->Link[ whichway ]; + } + } + + return( follower ); + } /* ubi_btLeafNode */ + +int ubi_btModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + list[1] = NULL; + return( 1 ); + } + return( 0 ); + } /* ubi_btModuleID */ + + +/* ========================================================================== */ diff --git a/source/ubi_BinTree.h b/source/ubi_BinTree.h new file mode 100644 index 00000000000..1be8cba8778 --- /dev/null +++ b/source/ubi_BinTree.h @@ -0,0 +1,745 @@ +#ifndef ubi_BinTree_H +#define ubi_BinTree_H +/* ========================================================================== ** + * ubi_BinTree.h + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height + * balancing, no restructuring. Still, a good tool for creating short, low- + * overhead sorted lists of things that need to be found in a hurry. + * + * In addition, this module provides a good basis for creating other types + * of binary tree handling modules. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.h,v $ + * Revision 1.1 1997/10/09 04:09:52 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.4 1997/07/26 04:11:14 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:15:27 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:40 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:43:46 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:33 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:55:04 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +/* -------------------------------------------------------------------------- ** + * Macros and constants. + * + * General purpose: + * ubi_trTRUE - Boolean TRUE. + * ubi_trFALSE - Boolean FALSE. + * + * Flags used in the tree header: + * ubi_trOVERWRITE - This flag indicates that an existing node may be + * overwritten by a new node with a matching key. + * ubi_trDUPKEY - This flag indicates that the tree allows duplicate + * keys. If the tree does allow duplicates, the + * overwrite flag is ignored. + * + * Node link array index constants: (Each node has an array of three + * pointers. One to the left, one to the right, and one back to the + * parent.) + * LEFT - Left child pointer. + * PARENT - Parent pointer. + * RIGHT - Right child pointer. + * EQUAL - Synonym for PARENT. + * + * ubi_trCompOps: These values are used in the ubi_trLocate() function. + * ubi_trLT - request the first instance of the greatest key less than + * the search key. + * ubi_trLE - request the first instance of the greatest key that is less + * than or equal to the search key. + * ubi_trEQ - request the first instance of key that is equal to the + * search key. + * ubi_trGE - request the first instance of a key that is greater than + * or equal to the search key. + * ubi_trGT - request the first instance of the first key that is greater + * than the search key. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trTRUE 0xFF +#define ubi_trFALSE 0x00 + +#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ +#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ + +/* Pointer array index constants... */ +#define LEFT 0x00 +#define PARENT 0x01 +#define RIGHT 0x02 +#define EQUAL PARENT + +typedef enum { + ubi_trLT = 1, + ubi_trLE, + ubi_trEQ, + ubi_trGE, + ubi_trGT + } ubi_trCompOps; + +/* -------------------------------------------------------------------------- ** + * These three macros allow simple manipulation of pointer index values (LEFT, + * RIGHT, and PARENT). + * + * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C + * uses {negative, zero, positive} values to indicate + * {less than, equal to, greater than}. + * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, + * RIGHT} (opposite of Normalize()). Note: C comparison + * functions, such as strcmp(), return {negative, zero, + * positive} values, which are not necessarily {-1, 0, + * 1}. This macro uses the the ubi_btSgn() function to + * compensate. + * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) + * is left as is. + * -------------------------------------------------------------------------- ** + */ +#define Normalize(W) ((char)((W)-EQUAL)) +#define AbNormal(W) ((char)( EQUAL+((char)ubi_btSgn( (W) )) )) +#define RevWay(W) ((char)((W)==LEFT?RIGHT:((W)==RIGHT?LEFT:EQUAL))) + +/* -------------------------------------------------------------------------- ** + * These macros allow us to quickly read the values of the OVERWRITE and + * DUPlicate KEY bits of the tree root flags field. + * -------------------------------------------------------------------------- ** + */ +#define Dups_OK(A) ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) +#define Ovwt_OK(A) ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) + +/* -------------------------------------------------------------------------- ** + * Typedefs... + * + * ubi_trBool - Your typcial true or false... + * + * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to + * indicate a key that is being searched for within the tree. + * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), + * or ubi_trInsert() functions are called. + * -------------------------------------------------------------------------- ** + */ + +typedef unsigned char ubi_trBool; + +typedef void *ubi_btItemPtr; /* A pointer to data within a node. */ + +/* ------------------------------------------------------------------------- ** + * Binary Tree Node Structure: This structure defines the basic elements of + * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! + * But, of course, I have to put the structure into this header so that + * you can use it as a building block. + * + * The fields are as follows: + * Link - an array of pointers. These pointers are manipulated by + * the BT routines. The pointers indicate the left and right + * child nodes and the parent node. By keeping track of the + * parent pointer, we avoid the need for recursive routines or + * hand-tooled stacks to keep track of our path back to the + * root. The use of these pointers is subject to change without + * notice. + * gender - a one-byte field indicating whether the node is the RIGHT or + * LEFT child of its parent. If the node is the root of the + * tree, gender will be PARENT. + * ------------------------------------------------------------------------- ** + */ +typedef struct ubi_btNodeStruct { + struct ubi_btNodeStruct *Link[ 3 ]; + char gender; + } ubi_btNode; + +typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ + +/* ------------------------------------------------------------------------- ** + * The next three typedefs define standard function types used by the binary + * tree management routines. In particular: + * + * ubi_btCompFunc is a pointer to a comparison function. Comparison + * functions are passed an ubi_btItemPtr and an + * ubi_btNodePtr. They return a value that is (<0), 0, + * or (>0) to indicate that the Item is (respectively) + * "less than", "equal to", or "greater than" the Item + * contained within the node. (See ubi_btInitTree()). + * ubi_btActionRtn is a pointer to a function that may be called for each + * node visited when performing a tree traversal (see + * ubi_btTraverse()). The function will be passed two + * parameters: the first is a pointer to a node in the + * tree, the second is a generic pointer that may point to + * anything that you like. + * ubi_btKillNodeRtn is a pointer to a function that will deallocate the + * memory used by a node (see ubi_btKillTree()). Since + * memory management is left up to you, deallocation may + * mean anything that you want it to mean. Just remember + * that the tree *will* be destroyed and that none of the + * node pointers will be valid any more. + * ------------------------------------------------------------------------- ** + */ + +typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); + +typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); + +typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); + +/* -------------------------------------------------------------------------- ** + * Tree Root Structure: This structure gives us a convenient handle for + * accessing whole AVL trees. The fields are: + * root - A pointer to the root node of the AVL tree. + * count - A count of the number of nodes stored in the tree. + * cmp - A pointer to the comparison routine to be used when building or + * searching the tree. + * flags - A set of bit flags. Two flags are currently defined: + * + * ubi_trOVERWRITE - If set, this flag indicates that a new node should + * (bit 0x01) overwrite an old node if the two have identical + * keys (ie., the keys are equal). + * ubi_trDUPKEY - If set, this flag indicates that the tree is + * (bit 0x02) allowed to contain nodes with duplicate keys. + * + * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. + * + * All of these values are set when you initialize the root structure by + * calling ubi_trInitTree(). + * -------------------------------------------------------------------------- ** + */ + +typedef struct { + ubi_btNodePtr root; /* A pointer to the root node of the tree */ + unsigned long count; /* A count of the number of nodes in the tree */ + ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ + unsigned char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ + } ubi_btRoot; + +typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ + + +/* -------------------------------------------------------------------------- ** + * Function Prototypes. + */ + +long ubi_btSgn( long x ); + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + unsigned char Flags ); + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ); + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ); + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Note that this function will return FALSE if either parameter + * is NULL. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: A boolean value. FALSE if either input parameter was NULL, else + * TRUE. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + + +int ubi_btModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#define ubi_trItemPtr ubi_btItemPtr + +#define ubi_trNode ubi_btNode +#define ubi_trNodePtr ubi_btNodePtr + +#define ubi_trRoot ubi_btRoot +#define ubi_trRootPtr ubi_btRootPtr + +#define ubi_trCompFunc ubi_btCompFunc +#define ubi_trActionRtn ubi_btActionRtn +#define ubi_trKillNodeRtn ubi_btKillNodeRtn + +#define ubi_trSgn( x ) ubi_btSgn( x ) + +#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) + +#define ubi_trInitTree( Rp, Cf, Fl ) \ + ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) + +#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) + +#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) + +#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) + +#define ubi_trFirstOf( Rp, Ip, P ) \ + ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trLastOf( Rp, Ip, P ) \ + ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trTraverse( Rp, En, Ud ) \ + ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) + +#define ubi_trKillTree( Rp, Fn ) \ + ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) + +#define ubi_trLeafNode( Nd ) \ + ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) + +/* ========================================================================== */ +#endif /* ubi_BinTree_H */ diff --git a/source/ubi_SplayTree.c b/source/ubi_SplayTree.c new file mode 100644 index 00000000000..d38e383d964 --- /dev/null +++ b/source/ubi_SplayTree.c @@ -0,0 +1,472 @@ +/* ========================================================================== ** + * ubi_SplayTree.c + * + * Copyright (C) 1993-1995 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.c,v $ + * Revision 1.1 1997/10/09 04:09:54 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.5 1997/07/26 04:15:42 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 04:42:21 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:07 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:54:42 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:46 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * Revision 1.1 93/10/18 20:35:16 CRH + * I removed the hard-coded logical device names from the include file + * specifications. CRH + * + * Revision 1.0 93/10/15 23:00:15 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.1 93/04/25 22:03:32 CRH + * Simply changed the <exec/types.h> #include reference the .c file to + * use <stdlib.h> instead. The latter is portable, the former is not. + * + * Revision 0.0 93/04/21 23:05:52 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include <stdlib.h> /* Defines NULL for us. */ +#include "ubi_SplayTree.h" /* Header for THIS module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_SplayTree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/09 04:09:54 $\n\ +\t$Author: crh $\n"; + + +/* ========================================================================== ** + * Private functions... + */ + +static void Rotate( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a single rotation, moving node *p up one level + * in the tree. + * + * Input: p - a pointer to an ubi_btNode in a tree. + * + * Output: None. + * + * Notes: This implements a single rotation in either direction (left + * or right). This is the basic building block of all splay + * tree rotations. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parentp; + ubi_btNodePtr tmp; + char way; + char revway; + + parentp = p->Link[PARENT]; /* Find parent. */ + + if( parentp ) /* If no parent, then we're already the root. */ + { + way = p->gender; + revway = RevWay(way); + tmp = p->Link[revway]; + + parentp->Link[way] = tmp; + if( tmp ) + { + tmp->Link[PARENT] = parentp; + tmp->gender = way; + } + + tmp = parentp->Link[PARENT]; + p->Link[PARENT] = tmp; + p->gender = parentp->gender; + if( tmp ) + tmp->Link[p->gender] = p; + + parentp->Link[PARENT] = p; + parentp->gender = revway; + p->Link[revway] = parentp; + } + } /* Rotate */ + +static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) + /* ------------------------------------------------------------------------ ** + * Move the node indicated by SplayWithMe to the root of the tree by + * splaying the tree. + * + * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. + * + * Output: A pointer to the root of the splay tree (i.e., the same as + * SplayWithMe). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parent; + + while( (parent = SplayWithMe->Link[PARENT]) ) + { + if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ + Rotate( parent ); + else + { + if( EQUAL != parent->gender ) /* Zig-Zag */ + Rotate( SplayWithMe ); + } + Rotate( SplayWithMe ); /* Zig */ + } /* while */ + return( SplayWithMe ); + } /* Splay */ + +/* ========================================================================== ** + * Exported utilities. + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP; + + if( !(OldNode) ) + OldNode = &OtherP; + + if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) + { + RootPtr->root = Splay( NewNode ); + return( ubi_trTRUE ); + } + + /* Splay the unreplacable, duplicate keyed, unique, old node. */ + RootPtr->root = Splay( (*OldNode) ); + return( ubi_trFALSE ); + } /* ubi_sptInsert */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + (void)Splay( DeadNode ); /* Move dead node to root. */ + if( (p = DeadNode->Link[LEFT]) ) /* If left subtree exists... */ + { + ubi_btNodePtr q = DeadNode->Link[RIGHT]; + + p->Link[PARENT] = NULL; /* Left subtree node becomes root.*/ + p->gender = PARENT; + p = ubi_btLast( p ); /* Find rightmost left tree node..*/ + p->Link[RIGHT] = q; /* ...attach right tree. */ + if( q ) + q->Link[PARENT] = p; + RootPtr->root = Splay( p ); /* Resplay at p. */ + } + else + { + if( (p = DeadNode->Link[RIGHT]) ) /* No left, but right subtree... */ + { /* ...exists... */ + p->Link[PARENT] = NULL; /* Right subtree root becomes... */ + p->gender = PARENT; /* ...overall tree root. */ + RootPtr->root = p; + } + else + RootPtr->root = NULL; /* No subtrees => empty tree. */ + } + + (RootPtr->count)--; /* Decrement node count. */ + return( DeadNode ); /* Return pointer to pruned node. */ + } /* ubi_sptRemove */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btLocate( RootPtr, FindMe, CompOp ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptLocate */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btFind( RootPtr, FindMe ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptFind */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ) + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + { + RootPtr->root = Splay( SplayMe ); + } /* ubi_sptSplay */ + +int ubi_sptModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_sptModuleID */ + +/* ================================ The End ================================= */ diff --git a/source/ubi_SplayTree.h b/source/ubi_SplayTree.h new file mode 100644 index 00000000000..6a17a19ec4f --- /dev/null +++ b/source/ubi_SplayTree.h @@ -0,0 +1,339 @@ +#ifndef ubi_SplayTree_H +#define ubi_SplayTree_H +/* ========================================================================== ** + * ubi_SplayTree.h + * + * Copyright (C) 1993,1995 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.h,v $ + * Revision 1.1 1997/10/09 04:09:55 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 2.5 1997/07/26 04:15:46 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 05:22:56 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:37 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:55:04 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:55 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * + * Revision 1.0 93/10/15 22:59:36 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.0 93/04/21 23:07:13 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ); + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + +int ubi_sptModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#undef ubi_trInsert +#undef ubi_trRemove +#undef ubi_trLocate +#undef ubi_trFind +#undef ubi_trModuleID + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_sptLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) + +/* ================================ The End ================================= */ +#endif /* ubi_SplayTree_H */ + + + + + diff --git a/source/ubi_dLinkList.c b/source/ubi_dLinkList.c new file mode 100644 index 00000000000..9c9ef3a73df --- /dev/null +++ b/source/ubi_dLinkList.c @@ -0,0 +1,152 @@ +/* ========================================================================== ** + * ubi_dLinkList.c + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_dLinkList.c,v $ + * Revision 1.1 1997/10/09 04:09:55 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 0.2 1997/10/08 03:07:21 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:07 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include "ubi_dLinkList.h" + +/* ========================================================================== ** + * Functions... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->Tail = NULL; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_dlInitList */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ) + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL == After ) + { + New->Next = ListPtr->Head; + New->Prev = NULL; + if( NULL != ListPtr->Head ) + ListPtr->Head->Prev = New; + else + ListPtr->Tail = New; + ListPtr->Head = New; + } + else + { + New->Next = After->Next; + New->Prev = After; + if( NULL != After->Next ) + After->Next->Prev = New; + else + ListPtr->Tail = New; + After->Next = New; + } + + ++(ListPtr->count); + + return( New ); + } /* ubi_dlInsert */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL != Old ) + { + if( Old->Next ) + Old->Next->Prev = Old->Prev; + else + ListPtr->Tail = Old->Prev; + + if( Old->Prev ) + Old->Prev->Next = Old->Next; + else + ListPtr->Head = Old->Next; + + --(ListPtr->count); + } + + return( Old ); + } /* ubi_dlRemove */ + + +/* ================================ The End ================================= */ diff --git a/source/ubi_dLinkList.h b/source/ubi_dLinkList.h new file mode 100644 index 00000000000..8aafd99704e --- /dev/null +++ b/source/ubi_dLinkList.h @@ -0,0 +1,163 @@ +#ifndef ubi_dLinkList_H +#define ubi_dLinkList_H +/* ========================================================================== ** + * ubi_dLinkList.h + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_dLinkList.h,v $ + * Revision 1.1 1997/10/09 04:09:56 crh + * This is my library of lists and trees. My hope is to replace all of the + * hard coded linked lists that are currently used in Samba with calls to + * these modules. This should make the code simpler, smaller, and (I hope) + * faster. The tree code, in particular, should speed up processing where + * large lists are involved. + * + * Chris -)----- + * + * Revision 0.2 1997/10/08 03:08:16 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:38 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include <stdlib.h> + + +/* ========================================================================== ** + * Typedefs... + * + * ubi_dlNode - This is the basic node structure. + * ubi_dlNodePtr - Pointer to a node. + * ubi_dlList - This is the list header structure. + * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_dlListNode + { + struct ubi_dlListNode *Next; + struct ubi_dlListNode *Prev; + } ubi_dlNode; + +typedef ubi_dlNode *ubi_dlNodePtr; + +typedef struct + { + ubi_dlNodePtr Head; + ubi_dlNodePtr Tail; + unsigned long count; + } ubi_dlList; + +typedef ubi_dlList *ubi_dlListPtr; + +/* ========================================================================== ** + * Macros... + * + * ubi_dlAddHead - Add a new node at the head of the list. + * ubi_dlAddTail - Add a new node at the tail of the list. + * ubi_dlRemHead - Remove the node at the head of the list, if any. + * ubi_dlRemTail - Remove the node at the tail of the list, if any. + * ubi_dlFirst - Return a pointer to the first node in the list, if any. + * ubi_dlLast - Return a pointer to the last node in the list, if any. + * ubi_dlNext - Given a node, return a pointer to the next node. + * ubi_dlPrev - Given a node, return a pointer to the previous node. + */ + +#define ubi_dlAddHead( L, N ) ubi_dlInsert( (L), (N), NULL ) + +#define ubi_dlAddTail( L, N ) ubi_dlInsert( (L), (N), ((L)->Tail) ) + +#define ubi_dlRemHead( L ) ubi_dlRemove( (L), ((L)->Head) ) + +#define ubi_dlRemTail( L ) ubi_dlRemove( (L), ((L)->Tail) ) + +#define ubi_dlFirst( L ) ((L)->Head) + +#define ubi_dlLast( L ) ((L)->Tail) + +#define ubi_dlNext( N ) ((N)->Next) + +#define ubi_dlPrev( N ) ((N)->Prev) + + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ); + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + + +/* ================================ The End ================================= */ +#endif /* ubi_dLinkList_H */ -- cgit From e10ba4b97a219e87b62d32834bf15ed2e323ed2e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 9 Oct 1997 06:36:04 +0000 Subject: bracket some macros change MAX_PASSWORD_LENGTH to MAX_PASS_LEN to prevent conflict on some systems add #ifdef around soft link dependent code (for systems that don't have soft links) --- source/client/clientutil.c | 2 +- source/include/includes.h | 8 ++++---- source/include/local.h | 2 +- source/smbd/reply.c | 10 +++++----- source/smbd/server.c | 4 ++++ 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/source/client/clientutil.c b/source/client/clientutil.c index ed5497782b3..01b4a093214 100644 --- a/source/client/clientutil.c +++ b/source/client/clientutil.c @@ -460,7 +460,7 @@ BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setu /* send a session setup command */ bzero(outbuf,smb_size); - if (passlen > MAX_PASSWORD_LENGTH) { + if (passlen > MAX_PASS_LEN) { DEBUG(1,("password too long %d\n", passlen)); return False; } diff --git a/source/include/includes.h b/source/include/includes.h index 4ca1d4c3b0d..a877f1ffb35 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -1114,15 +1114,15 @@ extern char *sys_errlist[]; #endif #ifndef S_ISREG -#define S_ISREG(x) ((S_IFREG & x)!=0) +#define S_ISREG(x) ((S_IFREG & (x))!=0) #endif #ifndef S_ISDIR -#define S_ISDIR(x) ((S_IFDIR & x)!=0) +#define S_ISDIR(x) ((S_IFDIR & (x))!=0) #endif #if !defined(S_ISLNK) && defined(S_IFLNK) -#define S_ISLNK(x) ((S_IFLNK & x)!=0) +#define S_ISLNK(x) ((S_IFLNK & (x))!=0) #endif #ifdef UFC_CRYPT @@ -1202,7 +1202,7 @@ it works and getting lots of bug reports */ /* this is a rough check to see if this machine has a lstat() call. it is not guaranteed to work */ -#if !(defined(S_ISLNK) || defined(S_IFLNK)) +#if !defined(S_ISLNK) #define lstat stat #endif diff --git a/source/include/local.h b/source/include/local.h index 3ce75eeb4e7..22d1b2a08e0 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -43,7 +43,7 @@ #define WORDMAX 0xFFFF /* the maximum password length before we declare a likely attack */ -#define MAX_PASSWORD_LENGTH 200 +#define MAX_PASS_LEN 200 /* separators for lists */ #define LIST_SEP " \t,;:\n\r" diff --git a/source/smbd/reply.c b/source/smbd/reply.c index fa641931eb2..2a3679553c0 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -252,7 +252,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); - if (passlen > MAX_PASSWORD_LENGTH) { + if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); } @@ -388,7 +388,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASSWORD_LENGTH) + if (smb_apasslen > MAX_PASS_LEN) { overflow_attack(smb_apasslen); } @@ -423,12 +423,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; - if (passlen1 > MAX_PASSWORD_LENGTH) { + if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); } - passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); - passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + passlen1 = MIN(passlen1, MAX_PASS_LEN); + passlen2 = MIN(passlen2, MAX_PASS_LEN); if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ diff --git a/source/smbd/server.c b/source/smbd/server.c index 2b906a76417..e4d433c06f9 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -214,9 +214,11 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) if (S_ISDIR(sbuf->st_mode)) result = aDIR | (result & aRONLY); +#ifdef S_ISLNK #if LINKS_READ_ONLY if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) result |= aRONLY; +#endif #endif /* hide files with a name starting with a . */ @@ -863,6 +865,7 @@ BOOL check_name(char *name,int cnum) /* Patch from David Clerc <David.Clerc@cui.unige.ch> University of Geneva */ +#ifdef S_ISLNK if (!lp_symlinks(SNUM(cnum))) { struct stat statbuf; @@ -873,6 +876,7 @@ BOOL check_name(char *name,int cnum) ret=0; } } +#endif if (!ret) DEBUG(5,("check_name on %s failed\n",name)); -- cgit From 4bf12a48435b3ec504439251638586c76742010c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 9 Oct 1997 06:47:20 +0000 Subject: change MAX_PASSWORD_LENGTH to MAX_PASS_LEN to prevent conflict on some systems --- source/include/local.h | 2 +- source/smbd/reply.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/include/local.h b/source/include/local.h index 9548bf74b6b..f5f2c318180 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -43,7 +43,7 @@ #define WORDMAX 0xFFFF /* the maximum password length before we declare a likely attack */ -#define MAX_PASSWORD_LENGTH 200 +#define MAX_PASS_LEN 200 /* separators for lists */ #define LIST_SEP " \t,;:\n\r" diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 31915e6acac..7925add45f3 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -251,7 +251,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); - if (passlen > MAX_PASSWORD_LENGTH) { + if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); } @@ -387,7 +387,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASSWORD_LENGTH) + if (smb_apasslen > MAX_PASS_LEN) { overflow_attack(smb_apasslen); } @@ -422,12 +422,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; - if (passlen1 > MAX_PASSWORD_LENGTH) { + if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); } - passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); - passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + passlen1 = MIN(passlen1, MAX_PASS_LEN); + passlen2 = MIN(passlen2, MAX_PASS_LEN); if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ -- cgit From dd6ac9b1eea3b0ace27fbd014b5ad4625c1fdf94 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 9 Oct 1997 10:01:12 +0000 Subject: an implementation of the NT domain credentials protocol --- source/libsmb/credentials.c | 101 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 source/libsmb/credentials.c diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c new file mode 100644 index 00000000000..efa0d83ec28 --- /dev/null +++ b/source/libsmb/credentials.c @@ -0,0 +1,101 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + code to manipulate domain credentials + Copyright (C) Andrew Tridgell 1997 + + 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" + + +/**************************************************************************** + setup the session key. +Input: 8 byte challenge block + 8 byte server challenge block + 16 byte md4 encrypted password +Output: + 8 byte session key +****************************************************************************/ +void cred_session_key(char *challenge, char *srv_challenge, char *pass, + char *session_key) +{ + uint32 sum[2]; + char sum2[8]; + char buf[8]; + + sum[0] = IVAL(challenge, 0) + IVAL(srv_challenge, 0); + sum[1] = IVAL(challenge, 4) + IVAL(srv_challenge, 4); + + SIVAL(sum2,0,sum[0]); + SIVAL(sum2,4,sum[1]); + + E1(pass,sum2,buf); + E1(pass+9,buf,session_key); +} + + +/**************************************************************************** +create a credential + +Input: + 8 byte sesssion key + 8 byte stored credential + 4 byte timestamp + +Output: + 8 byte credential +****************************************************************************/ +void cred_create(char *session_key, char *stored_cred, uint32 time, + char *cred) +{ + char key2[7]; + char buf[8]; + char timecred[8]; + + memcpy(timecred, stored_cred, 8); + SIVAL(timecred, 0, IVAL(stored_cred, 0) + time); + + E1(session_key, timecred, buf); + memset(key2, 0, 7); + key2[0] = session_key[7]; + E1(key2, buf, cred); +} + + +/**************************************************************************** + check a supplied credential + +Input: + 8 byte received credential + 8 byte sesssion key + 8 byte stored credential + 4 byte timestamp + +Output: + returns 1 if computed credential matches received credential + returns 0 otherwise +****************************************************************************/ +int cred_assert(char *cred, char *session_key, char *stored_cred, + uint32 time) +{ + char cred2[8]; + + cred_create(session_key, stored_cred, time, cred2); + + return memcmp(cred, cred2, 8) == 0; +} + -- cgit From 135d054e831cd0f5962acc05d03b38360b73827e Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Thu, 9 Oct 1997 11:24:39 +0000 Subject: JHT ===> Added smbadduser contributed by Mike Zakharoff. --- source/smbadduser | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 source/smbadduser diff --git a/source/smbadduser b/source/smbadduser new file mode 100755 index 00000000000..789cc927eb1 --- /dev/null +++ b/source/smbadduser @@ -0,0 +1,74 @@ +#!/bin/csh +# +# smbadduser - Written by Mike Zakharoff +# +unalias * +set path = ($path /usr/local/samba/bin) + +set smbpasswd = /usr/local/samba/private/smbpasswd +set user_map = /usr/local/samba/lib/users.map +# +# Set to site specific passwd command +# +#set passwd = "cat /etc/passwd" +#set passwd = "niscat passwd.org_dir" +set passwd = "ypcat passwd" + +set line = "----------------------------------------------------------" +if ($#argv == 0) then + echo $line + echo "Written: Mike Zakharoff email: michael.j.zakharoff@boeing.com" + echo "" + echo " 1) Updates $smbpasswd" + echo " 2) Updates $user_map" + echo " 3) Executes smbpasswd for each new user" + echo "" + echo "smbadduser unixid:ntid unixid:ntid ..." + echo "" + echo "Example: smbadduser zak:zakharoffm johns:smithj" + echo $line + exit 1 +endif + +touch $smbpasswd $user_map +set new = () +foreach one ($argv) + echo $one | grep ':' >& /dev/null + if ($status != 0) then + echo "ERROR: Must use unixid:ntid like -> zak:zakharoffm" + continue + endif + set unix = `echo $one | awk -F: '{print $1}'` + set ntid = `echo $one | awk -F: '{print $2}'` + + set usr = `eval $passwd | awk -F: '$1==USR {print $1}' USR=$unix` + if ($#usr != 1) then + echo "ERROR: $unix Not in passwd database SKIPPING..." + continue + endif + set tmp = `cat $smbpasswd | awk -F: '$1==USR {print $1}' USR=$unix` + if ($#tmp != 0) then + echo "ERROR: $unix is already in $smbpasswd SKIPPING..." + continue + endif + + echo "Adding: $unix to $smbpasswd" + eval $passwd | \ + awk -F: '$1==USR { \ + printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", +$1, $3, $5, $6, $7) }' USR=$unix >> $smbpasswd + if ($unix != $ntid) then + echo "Adding: {$unix = $ntid} to $user_map" + echo "$unix = $ntid" >> $user_map + endif + set new = ($new $unix) +end + +# +# Enter password for new users +# +foreach one ($new) + echo $line + echo "ENTER password for $one" + smbpasswd $one +end \ No newline at end of file -- cgit From 72a86f514f0c92b69499718e63f5dd73ebece56e Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 9 Oct 1997 14:40:46 +0000 Subject: credentials.c: use UTIME structure (defined and commented in smb.h to be time, secs, since 01jan1970) pipes.c: another sub-function. util.c: added char *unistr2(uint16 *buff) function. same as unistr except it takes uint16* instead of char*. smbparse.c smb.h: more structure sorting. proto.h: the usual. --- source/include/proto.h | 3 + source/include/smb.h | 6 +- source/lib/util.c | 28 ++++++- source/libsmb/credentials.c | 8 +- source/smbd/pipes.c | 190 +++++++++++++++++++++++++++++++++++++++++++- source/smbparse.c | 2 +- 6 files changed, 224 insertions(+), 13 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index fab69de3d1a..b0589ede190 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -628,6 +628,7 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); +char *dom_sid_to_string(DOM_SID *sid); /*The following definitions come from predict.c */ @@ -653,6 +654,7 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); +BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); /*The following definitions come from replace.c */ @@ -1040,6 +1042,7 @@ BOOL is_myname(char *s); void set_remote_arch(enum remote_arch_types type); enum remote_arch_types get_remote_arch(); char *skip_unicode_string(char *buf,int n); +char *unistr2(uint16 *buf); char *unistr(char *buf); int unistrncpy(char *dst, char *src, int len); int unistrcpy(char *dst, char *src); diff --git a/source/include/smb.h b/source/include/smb.h index 9f5279fca00..7d7677b3fc8 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -565,11 +565,7 @@ typedef struct lsa_r_lookup_sids typedef struct dom_name_info { uint32 uni_str_len; -#if 1 /* don't know if buffer is null-terminated */ - UNISTR buffer; -#else /* or length indicated by uni_str_len member */ - uint16 buffer[MAX_UNISTRLEN]; -#endif + UNISTR str; } DOM_NAME; diff --git a/source/lib/util.c b/source/lib/util.c index 39d3c61b9e3..701f3245541 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4216,7 +4216,27 @@ char *skip_unicode_string(char *buf,int n) /******************************************************************* Return a ascii version of a unicode string -Hack alert: uses fixed buffer and only handles ascii strings +Hack alert: uses fixed buffer(s) and only handles ascii strings +********************************************************************/ +#define MAXUNI 1024 +char *unistr2(uint16 *buf) +{ + static char lbufs[8][MAXUNI]; + static int nexti; + char *lbuf = lbufs[nexti]; + char *p; + nexti = (nexti+1)%8; + for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++) + { + *p = *buf; + } + *p = 0; + return lbuf; +} + +/******************************************************************* +Return a ascii version of a unicode string +Hack alert: uses fixed buffer(s) and only handles ascii strings ********************************************************************/ #define MAXUNI 1024 char *unistr(char *buf) @@ -4225,9 +4245,13 @@ char *unistr(char *buf) static int nexti; char *lbuf = lbufs[nexti]; char *p; + nexti = (nexti+1)%8; - for (p = lbuf; *buf && p -lbuf < MAXUNI-2; p++, buf += 2) + + for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2) + { *p = *buf; + } *p = 0; return lbuf; } diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index efa0d83ec28..4c81177fb20 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -59,7 +59,7 @@ Input: Output: 8 byte credential ****************************************************************************/ -void cred_create(char *session_key, char *stored_cred, uint32 time, +void cred_create(char *session_key, char *stored_cred, UTIME timestamp, char *cred) { char key2[7]; @@ -67,7 +67,7 @@ void cred_create(char *session_key, char *stored_cred, uint32 time, char timecred[8]; memcpy(timecred, stored_cred, 8); - SIVAL(timecred, 0, IVAL(stored_cred, 0) + time); + SIVAL(timecred, 0, IVAL(stored_cred, 0) + timestamp.time); E1(session_key, timecred, buf); memset(key2, 0, 7); @@ -90,11 +90,11 @@ Output: returns 0 otherwise ****************************************************************************/ int cred_assert(char *cred, char *session_key, char *stored_cred, - uint32 time) + NTTIME timestamp) { char cred2[8]; - cred_create(session_key, stored_cred, time, cred2); + cred_create(session_key, stored_cred, timestamp, cred2); return memcmp(cred, cred2, 8) == 0; } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index bedf847cc43..13cdff262d7 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -370,6 +370,20 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* RID username mapping function. just for fun, it maps to the unix uid */ +static uint32 name_to_rid(char *user_name) +{ + struct passwd *pw = Get_Pwnam(user_name, False); + if (!pw) + { + DEBUG(1,("Username %s is invalid on this system\n", user_name)); + return (uint32)(-1); + } + + return (uint32)(pw->pw_uid); +} + + /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ char *dom_sid_to_string(DOM_SID *sid) { @@ -504,6 +518,14 @@ static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) str->buffer[len] = (uint16)terminate; } +static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) +{ + rid2->type = 0x5; + rid2->undoc = 0x5; + rid2->rid = rid; + rid2->rid_idx = 0; +} + static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) { int len_sid_str = strlen(sid_str); @@ -585,6 +607,28 @@ static void make_dom_ref(DOM_R_REF *ref, make_dom_sid(&(ref->ref_dom[3]), other_sid3); } +static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); + } + + r_l->num_entries3 = num_entries; +} + static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], char *dom_name, char *dom_sid, @@ -627,6 +671,26 @@ static int lsa_reply_lookup_sids(char *q, char *base, return q - start; } +static int lsa_reply_lookup_rids(char *q, char *base, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + char *start = q; + LSA_R_LOOKUP_RIDS r_l; + + /* set up the LSA Lookup RIDs response */ + make_reply_lookup_rids(&r_l, num_entries, dom_rids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4); + + /* return length of SMB data stored */ + return q - start; +} + static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) { memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); @@ -952,6 +1016,129 @@ static void api_lsa_lookup_sids( char *param, char *data, *rdata_len = reply_len + 0x18; } +static void api_lsa_lookup_names( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_LOOKUP_RIDS q_l; + pstring dom_name; + pstring dom_sid; + uint32 dom_rids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received RIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + char *user_name = unistr2(q_l.lookup_name[i].str.buffer); + dom_rids[i] = name_to_rid(user_name); + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + q_l.num_entries, dom_rids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; +} + +#if 0 + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { +qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { +qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ +qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); +qSIVAL(name_to_rid(names[i])); + DEBUG(4,("lookupnames name_to_rid %d\n",name_to_rid(names[i]))); +qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + +#endif + + /* space in front of this function so that make proto doesn't pick it up */ void _dummy_function(void) { @@ -971,5 +1158,6 @@ static void api_lsa_lookup_sids( char *param, char *data, lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); api_lsa_open_policy(NULL,NULL,NULL,NULL); api_lsa_query_info(NULL,NULL,NULL,NULL); - api_lsa_lookup_sids(NULL,NULL,NULL,NULL); + api_lsa_lookup_sids (NULL,NULL,NULL,NULL); + api_lsa_lookup_names(NULL,NULL,NULL,NULL); } diff --git a/source/smbparse.c b/source/smbparse.c index 0d93c2e8ad5..01438281ef1 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -513,7 +513,7 @@ char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align) /* don't know if len is specified by uni_str_len member... */ /* assume unicode string is unicode-null-terminated, instead */ - q = smb_io_unistr(io, &(name->buffer), q, base, align); + q = smb_io_unistr(io, &(name->str), q, base, align); return q; } -- cgit From 5437f666987918516032cf8a5dada107e5d14d25 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 9 Oct 1997 15:48:40 +0000 Subject: pipes.c: added api_ntlsarpcTNP() function. hooray! smb.h: added LSA #defines needed by above function. --- source/include/smb.h | 38 ++ source/smbd/pipes.c | 1175 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 1131 insertions(+), 82 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 7d7677b3fc8..d0baa669928 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -4,6 +4,8 @@ SMB parameters and setup Copyright (C) Andrew Tridgell 1992-1997 Copyright (C) John H Terpstra 1996-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 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 @@ -256,6 +258,42 @@ typedef char fstring[128]; typedef fstring string; +/* NETLOGON opcodes and data structures */ + +#define NET_QUERYFORPDC 7 /* Query for PDC */ +#define NET_QUERYFORPDC_R 12 /* Response to Query for PDC */ +#define NET_SAMLOGON 18 +#define NET_SAMLOGON_R 19 + +/* Allowable account control bits */ +#define ACB_DISABLED 1 /* 1 = User account disabled */ +#define ACB_HOMDIRREQ 2 /* 1 = Home directory required */ +#define ACB_PWNOTREQ 4 /* 1 = User password not required */ +#define ACB_TEMPDUP /* 1 = Temporary duplicate account */ +#define ACB_NORMAL /* 1 = Normal user account */ +#define ACB_MNS /* 1 = MNS logon user account */ +#define ACB_DOMTRUST /* 1 = Interdomain trust account */ +#define ACB_WSTRUST /* 1 = Workstation trust account */ +#define ACB_SVRTRUST /* 1 = Server trust account */ +#define ACB_PWNOEXP /* 1 = User password does not expire */ +#define ACB_AUTOLOCK /* 1 = Account auto locked */ + +#define LSA_OPENPOLICY 0x2c +#define LSA_QUERYINFOPOLICY 0x07 +#define LSA_ENUMTRUSTDOM 0x0d +#define LSA_REQCHAL 0x04 +#define LSA_SVRPWSET 0x06 +#define LSA_SAMLOGON 0x02 +#define LSA_AUTH2 0x0f +#define LSA_CLOSE 0x00 + +/* unknown .... */ +#define LSA_OPENSECRET 0xFF +#define LSA_LOOKUPSIDS 0xFE +#define LSA_LOOKUPNAMES 0xFD +#define LSA_SAMLOGOFF 0xFC + + /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ typedef struct time_info { diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 13cdff262d7..4dd7aa3e30a 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -3,8 +3,8 @@ Version 1.9. Pipe SMB reply routines Copyright (C) Andrew Tridgell 1992-1997, - Paul Ashton 1997, - Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 1997. 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 @@ -370,6 +370,36 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, fragment length. I've decided to do it based on operation number :-) */ +/* this function is due to be replaced */ +static void initrpcreply(char *inbuf, char *q) +{ + uint32 callid; + + SCVAL(q, 0, 5); q++; /* RPC version 5 */ + SCVAL(q, 0, 0); q++; /* minor version 0 */ + SCVAL(q, 0, 2); q++; /* RPC response packet */ + SCVAL(q, 0, 3); q++; /* first frag + last frag */ + RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ + RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ + SSVAL(q, 0, 0); q += 2; /* authentication length */ + callid = RIVAL(inbuf, 12); + RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ + SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ + SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ + SCVAL(q, 0, 0); q++; /* cancel count */ + SCVAL(q, 0, 0); q++; /* reserved */ +} + +/* this function is due to be replaced */ +static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) +{ + SSVAL(q, 8, datalen + 4); + SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ + SIVAL(q, datalen, rtnval); + *rlen = datalen + 4; + { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } +} + /* RID username mapping function. just for fun, it maps to the unix uid */ static uint32 name_to_rid(char *user_name) { @@ -1051,94 +1081,1079 @@ static void api_lsa_lookup_names( char *param, char *data, *rdata_len = reply_len + 0x18; } -#if 0 - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) +BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + + int pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + switch (opnum) + { + case LSA_OPENPOLICY: + { + DEBUG(3,("LSA_OPENPOLICY\n")); + api_lsa_open_policy(param, data, rdata, rdata_len); + break; + } + + case LSA_QUERYINFOPOLICY: + { + DEBUG(3,("LSA_QUERYINFOPOLICY\n")); + + api_lsa_query_info(param, data, rdata, rdata_len); + break; + } + + case LSA_ENUMTRUSTDOM: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_ENUMTRUSTDOM\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); /* enumeration context */ + SIVAL(q, 0, 4); /* entries read */ + SIVAL(q, 0, 8); /* trust information */ + + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + + break; + } + + case LSA_CLOSE: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_CLOSE\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + + break; + } + + case LSA_OPENSECRET: + { + char *q = *rdata + 0x18; + DEBUG(3,("LSA_OPENSECRET\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + + break; + } + + case LSA_LOOKUPSIDS: + { + DEBUG(3,("LSA_OPENSECRET\n")); + api_lsa_lookup_sids(param, data, rdata, rdata_len); + break; + } + + case LSA_LOOKUPNAMES: + { + DEBUG(3,("LSA_LOOKUPNAMES\n")); + api_lsa_lookup_names(param, data, rdata, rdata_len); + break; + } + + default: + { + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + break; + } + } + return True; +} + + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + + BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) { -qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + char *q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { -qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ -qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); -qSIVAL(name_to_rid(names[i])); - DEBUG(4,("lookupnames name_to_rid %d\n",name_to_rid(names[i]))); -qSIVAL(0); /* domain index out of above reference domains */ + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; -#endif + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +static void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + +static void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; +#endif /* NTDOMAIN */ /* space in front of this function so that make proto doesn't pick it up */ void _dummy_function(void) { @@ -1156,8 +2171,4 @@ qSIVAL(0); /* domain index out of above reference domains */ NULL, NULL); lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); - api_lsa_open_policy(NULL,NULL,NULL,NULL); - api_lsa_query_info(NULL,NULL,NULL,NULL); - api_lsa_lookup_sids (NULL,NULL,NULL,NULL); - api_lsa_lookup_names(NULL,NULL,NULL,NULL); } -- cgit From d9fcf11aa04ff04dcbccd628322240f8324ae51d Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 9 Oct 1997 15:51:43 +0000 Subject: moved the array macros outside of the CAREFUL_ALIGNMENT define. --- source/include/byteorder.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index 4991338f263..0664a338175 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -128,6 +128,7 @@ it also defines lots of intermediate macros, just ignore those :-) #if CAREFUL_ALIGNMENT + #define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) #define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) @@ -138,7 +139,9 @@ it also defines lots of intermediate macros, just ignore those :-) #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) #define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) #define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) + #else + /* this handles things for architectures like the 386 that can handle alignment errors */ /* @@ -158,6 +161,11 @@ it also defines lots of intermediate macros, just ignore those :-) #define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) #define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) +#endif + + +/* macros for reading / writing arrays */ + #define SMBMACRO(macro,buf,pos,val,len,size) \ { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); } @@ -180,8 +188,6 @@ it also defines lots of intermediate macros, just ignore those :-) #define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2) #define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4) -#endif - /* now the reverse routines - these are used in nmb packets (mostly) */ #define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) @@ -191,3 +197,4 @@ it also defines lots of intermediate macros, just ignore those :-) #define RIVAL(buf,pos) IREV(IVAL(buf,pos)) #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) + -- cgit From 7bc4c4c27bf18ce3f632d230dc919ea341b5abb0 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 9 Oct 1997 16:14:53 +0000 Subject: added #ifdef NTDOMAIN. added call to api_ntLsarpc instead of api_Lsarpc in ipc.c iff NTDOMAIN is defined. --- source/include/proto.h | 4 + source/smbd/ipc.c | 4 + source/smbd/pipes.c | 984 +------------------------------------------------ 3 files changed, 11 insertions(+), 981 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index b0589ede190..009d83db5c2 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -629,6 +629,10 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len); char *dom_sid_to_string(DOM_SID *sid); +BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); /*The following definitions come from predict.c */ diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 6da9562c9f4..28cdb22889a 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2763,7 +2763,11 @@ struct } api_fd_commands [] = { { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, +#ifdef NTDOMAIN + { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, +#else { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, +#endif { NULL, NULL, -1, (BOOL (*)())api_Unsupported } }; diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 4dd7aa3e30a..6937412e29f 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -54,7 +54,7 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { "lsarpc", -#if 0 +#if NTDOMAIN "NETLOGON", #endif NULL @@ -364,6 +364,8 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } + +#ifdef NTDOMAIN /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -1191,984 +1193,4 @@ BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, return True; } - -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - - BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - char *q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; - - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ - - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - } - return(True); -} - - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - } - return(True); -} - -static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} - -static void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} - -static void setsesskey(int cnum) -{ - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); -} - -static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; - - #endif /* NTDOMAIN */ -/* space in front of this function so that make proto doesn't pick it up */ - void _dummy_function(void) -{ - UTIME t; - lsa_reply_req_chal(NULL, NULL, NULL, NULL); - lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0); - lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0); - make_lsa_user_info(NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - 0, 0, - 0, 0, 0, NULL, 0, - NULL, - NULL, NULL, - NULL, NULL); - lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL); - lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0); -} -- cgit From 76247228896d39312ba896fa229076be3271e2e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Thu, 9 Oct 1997 18:40:52 +0000 Subject: local.h: Fix spelling mistake :-). namedbsubnet.c: Stop registering 1x name unless we can be a local master. reply.c: Remove ERRbaddirectory code. server.c: Remove abort() - use exit_server() instead. trans2.c: Remove ERRbaddirectory code. Jeremy (jallison@whistle.com) --- source/include/local.h | 2 +- source/namedbsubnet.c | 6 +++++- source/smbd/reply.c | 4 +++- source/smbd/server.c | 2 +- source/smbd/trans2.c | 9 +++++++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/source/include/local.h b/source/include/local.h index 22d1b2a08e0..97857727c74 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -159,7 +159,7 @@ /* the directory to sit in when idle */ /* #define IDLE_DIR "/" */ -/* Timout (in seconds) to wait for an oplock breal +/* Timout (in seconds) to wait for an oplock break message to return. */ #define OPLOCK_BREAK_TIMEOUT 30 diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c index 4f0b647996d..c6663d71fd4 100644 --- a/source/namedbsubnet.c +++ b/source/namedbsubnet.c @@ -218,7 +218,11 @@ void add_workgroup_to_subnet( struct subnet_record *d, char *group) int n; add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP); - add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP); + + /* Only register the WORKGROUP<0x1e> name if we could be a local master + browser. */ + if(lp_local_master()) + add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP); /* Add all our server names to the workgroup list. We remove any browser or logon server flags from all but the primary name. diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 2a3679553c0..baccb762911 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -641,13 +641,15 @@ int reply_chkpth(char *inbuf,char *outbuf) unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif return(UNIXERROR(ERRDOS,ERRbadpath)); } diff --git a/source/smbd/server.c b/source/smbd/server.c index e4d433c06f9..d387b7375bb 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -2774,7 +2774,7 @@ inode = %x).\n", fsp->name, fnum, dev, inode)); { DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", global_oplocks_open)); - abort(); + exit_server("oplock_break: global_oplocks_open < 0"); } DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 7f46604cce9..092a069a6e3 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -608,13 +608,15 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif return(ERROR(ERRDOS,ERRbadpath)); } @@ -651,13 +653,16 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_code = ERRbadpath; } - /* Ugly - NT specific hack - but needed (JRA) */ +#if 0 + /* Ugly - NT specific hack - maybe not needed ? (JRA) */ if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) { unix_ERR_class = ERRDOS; unix_ERR_code = ERRbaddirectory; } +#endif + return (UNIXERROR(ERRDOS,ERRbadpath)); } return(ERROR(ERRDOS,ERRbadpath)); -- cgit From f9df5ac008e368af86addee058f75c7e79ca74ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Thu, 9 Oct 1997 18:48:12 +0000 Subject: Added definition of oplocks parameter. Jeremy (jallison@whistle.com) --- docs/manpages/smb.conf.5 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 989a395c159..bb43941439a 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -596,6 +596,8 @@ only guest only user +oplocks + path postexec @@ -2236,6 +2238,22 @@ of the user. .B Example: only user = True +.SS oplocks (S) +This boolean option tells smbd whether to issue oplocks (opportunistic +locks) to file open requests on this share. The oplock code was introduced in +Samba 1.9.18 and can dramatically (approx 30% or more) improve the speed +of access to files on Samba servers. It allows the clients to agressively +cache files locally and you may want to disable this option for unreliable +network environments (it is turned on by default in Windows NT Servers). +For more information see the file Speed.txt in the Samba docs/ directory. + +.B Default: + oplocks = True + +.B Example: + oplocks = False + + .SS os level (G) This integer value controls what level Samba advertises itself as for browse elections. See BROWSING.txt for details. -- cgit From 229b6c409240a8dca9172702b8fefb31aa3b13a1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Thu, 9 Oct 1997 20:30:29 +0000 Subject: Added in oplock info. Jeremy (jallison@whistle.com) --- docs/textdocs/Speed.txt | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/docs/textdocs/Speed.txt b/docs/textdocs/Speed.txt index b11885fc377..cb086a97112 100644 --- a/docs/textdocs/Speed.txt +++ b/docs/textdocs/Speed.txt @@ -43,21 +43,36 @@ only one accessing the file and it will agressively cache file data. With some oplock types the client may even cache file open/close operations. This can give enormous performance benefits. -Samba does not support opportunistic locks because they are very -difficult to do under Unix. Samba can fake them, however, by granting -a oplock whenever a client asks for one. This is controlled using the -smb.conf option "fake oplocks". If you set "fake oplocks = yes" then -you are telling the client that it may agressively cache the file -data. - -By enabling this option on all read-only shares or shares that you know +With the release of Samba 1.9.18 we now correctly support opportunistic +locks. This is turned on by default, and can be turned off on a share- +by-share basis by setting the parameter : + +oplocks = False + +We recommend that you leave oplocks on however, as current benchmark +tests with NetBench seem to give approximately a 30% improvement in +speed with them on. This is on average however, and the actual +improvement seen can be orders of magnitude greater, depending on +what the client redirector is doing. + +Previous to Samba 1.9.18 there was a 'fake oplocks' option. This +option has been left in the code for backwards compatibility reasons +but it's use is now deprecated. A short summary of what the old +code did follows. + +Old 'fake oplocks' option - deprecated. +--------------------------------------- + +Samba can also fake oplocks, by granting a oplock whenever a client +asks for one. This is controlled using the smb.conf option "fake +oplocks". If you set "fake oplocks = yes" then you are telling the +client that it may agressively cache the file data for all opens. + +Enabling 'fake oplocks' on all read-only shares or shares that you know will only be accessed from one client at a time you will see a big performance improvement on many operations. If you enable this option on shares where multiple clients may be accessing the files read-write -at the same time you can get data corruption. Use this option -carefully! - -This option is disabled by default. +at the same time you can get data corruption. SOCKET OPTIONS -------------- -- cgit From 53915bd160eda8c099482ddcef74d1d7606e752b Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Fri, 10 Oct 1997 01:32:26 +0000 Subject: nmblookup.c: Added -A ability to do status on ip address. smb.h: Added defines we will need for NT SMB calls. trans2.c: Fixed SMB_QUERY_FILE_ALT_NAME_INFO return - this is only for short name returns (and only used when you negotiate NT SMB calls to boot !). Jeremy (jallison@whistle.com) --- source/include/smb.h | 53 +++++++++++++++++++++++++++++++----------------- source/smbd/trans2.c | 22 +++++++++++++++++++- source/utils/nmblookup.c | 18 +++++++++++++++- 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index d0baa669928..54ce9e88e88 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -438,8 +438,8 @@ typedef struct id_info_1 DOM_LOGON_ID logon_id; /* logon ID */ UNIHDR hdr_user_name; /* user name unicode header */ UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ - ARC4_OWF arc4_lm_owf; /* rc4 LM OWF Password */ - ARC4_OWF arc4_nt_owf; /* rc4 NT OWF Password */ + ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ + ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ UNISTR2 uni_domain_name; /* domain name unicode string */ UNISTR2 uni_user_name; /* user name unicode string */ UNISTR2 uni_workgroup_name; /* workgroup name unicode string */ @@ -1305,23 +1305,38 @@ struct connect_record #define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ #define SMBulogoffX 0x74 /* user logoff */ - -/* these are the TRANS2 sub commands */ -#define TRANSACT2_OPEN 0 -#define TRANSACT2_FINDFIRST 1 -#define TRANSACT2_FINDNEXT 2 -#define TRANSACT2_QFSINFO 3 -#define TRANSACT2_SETFSINFO 4 -#define TRANSACT2_QPATHINFO 5 -#define TRANSACT2_SETPATHINFO 6 -#define TRANSACT2_QFILEINFO 7 -#define TRANSACT2_SETFILEINFO 8 -#define TRANSACT2_FSCTL 9 -#define TRANSACT2_IOCTL 10 -#define TRANSACT2_FINDNOTIFYFIRST 11 -#define TRANSACT2_FINDNOTIFYNEXT 12 -#define TRANSACT2_MKDIR 13 - +/* NT SMB extensions. */ +#define SMBnttrans 0xA0 /* NT transact */ +#define SMBnttranss 0xA1 /* NT transact secondary */ +#define SMBntcreateX 0xA2 /* NT create and X */ +#define SMBntcancel 0xA4 /* NT cancel */ + +/* These are the TRANS2 sub commands */ +#define TRANSACT2_OPEN 0 +#define TRANSACT2_FINDFIRST 1 +#define TRANSACT2_FINDNEXT 2 +#define TRANSACT2_QFSINFO 3 +#define TRANSACT2_SETFSINFO 4 +#define TRANSACT2_QPATHINFO 5 +#define TRANSACT2_SETPATHINFO 6 +#define TRANSACT2_QFILEINFO 7 +#define TRANSACT2_SETFILEINFO 8 +#define TRANSACT2_FSCTL 9 +#define TRANSACT2_IOCTL 0xA +#define TRANSACT2_FINDNOTIFYFIRST 0xB +#define TRANSACT2_FINDNOTIFYNEXT 0xC +#define TRANSACT2_MKDIR 0xD +#define TRANSACT2_SESSION_SETUP 0xE +#define TRANSACT2_GET_DFS_REFERRAL 0x10 +#define TRANSACT2_REPORT_DFS_INCONSISTANCY 0x11 + +/* These are the NT transact sub commands. */ +#define NT_TRANSACT_CREATE 1 +#define NT_TRANSACT_IOCTL 2 +#define NT_TRANSACT_SET_SECURITY_DESC 3 +#define NT_TRANSACT_NOTIFY_CHANGE 4 +#define NT_TRANSACT_RENAME 5 +#define NT_TRANSACT_QUERY_SECURITY_DESC 6 /* these are the trans2 sub fields for primary requests */ #define smb_tpscnt smb_vwv0 diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 092a069a6e3..a56df9cb9cc 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1181,12 +1181,32 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, data_size = 4; break; - case SMB_QUERY_FILE_NAME_INFO: + /* Get the 8.3 name - used if NT SMB was negotiated. */ case SMB_QUERY_FILE_ALT_NAME_INFO: + { + pstring short_name; + pstrcpy(short_name,fname); + /* Mangle if not already 8.3 */ + if(!is_8_3(short_name, True)) + { + if(!name_map_mangle(short_name,True,SNUM(cnum))) + *short_name = '\0'; + } + strncpy(pdata + 4,short_name,12); + (pdata + 4)[12] = 0; + strupper(pdata + 4); + l = strlen(pdata + 4); + data_size = 4 + l; + SIVAL(pdata,0,l); + } + break; + + case SMB_QUERY_FILE_NAME_INFO: data_size = 4 + l; SIVAL(pdata,0,l); pstrcpy(pdata+4,fname); break; + case SMB_QUERY_FILE_ALLOCATION_INFO: case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c index 36905aa5ae3..63ca156449f 100644 --- a/source/utils/nmblookup.c +++ b/source/utils/nmblookup.c @@ -88,6 +88,8 @@ static void usage(void) printf("\t-B broadcast address the address to use for broadcasts\n"); printf("\t-M searches for a master browser\n"); printf("\t-S lookup node status as well\n"); + printf("\t-r Use root port 137 (Win95 only replies to this)\n"); + printf("\t-A Do a node status on <name> as an IP Address\n"); printf("\n"); } @@ -108,6 +110,7 @@ int main(int argc,char *argv[]) static pstring servicesf = CONFIGFILE; struct in_addr bcast_addr; BOOL got_bcast = False; + BOOL lookup_by_ip = False; DEBUGLEVEL = 1; *lookup = 0; @@ -118,7 +121,7 @@ int main(int argc,char *argv[]) charset_initialise(); - while ((opt = getopt(argc, argv, "d:B:i:s:SMrh")) != EOF) + while ((opt = getopt(argc, argv, "d:B:i:s:SMrhA")) != EOF) switch (opt) { case 'B': @@ -149,6 +152,9 @@ int main(int argc,char *argv[]) usage(); exit(0); break; + case 'A': + lookup_by_ip = True; + break; default: usage(); exit(1); @@ -182,6 +188,16 @@ int main(int argc,char *argv[]) fstrcpy(lookup,argv[i]); + if(lookup_by_ip) + { + strcpy(lookup,"*"); + ip = *interpret_addr2(argv[i]); + printf("Looking up status of %s\n",inet_ntoa(ip)); + name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL); + printf("\n"); + continue; + } + if (find_master) { if (*lookup == '-') { strcpy(lookup,"\01\02__MSBROWSE__\02"); -- cgit From 1448f528b60402170257c1cdf6831cc40b4c86c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 10 Oct 1997 02:32:01 +0000 Subject: fixed the log wrapping bug. This is a very nasty bug that I think explains quite a few intermittent problems people have been having with Samba. It may be worth checking on other cases where errno can be overwritten by seemingly innocuous things (in this case a DEBUG() line) --- source/lib/util.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/source/lib/util.c b/source/lib/util.c index 701f3245541..4e6bfb7054a 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -156,7 +156,7 @@ static void check_log_size(void) int maxlog; struct stat st; - if (debug_count++ < 100) return; + if (debug_count++ < 100 || getuid() != 0) return; maxlog = lp_max_log_size() * 1024; if (!dbf || maxlog <= 0) return; @@ -190,7 +190,8 @@ va_dcl char *format_str; #endif va_list ap; - + int old_errno = errno; + if (stdout_logging) { #ifdef __STDC__ va_start(ap, format_str); @@ -200,6 +201,7 @@ va_dcl #endif vfprintf(dbf,format_str,ap); va_end(ap); + errno = old_errno; return(0); } @@ -207,16 +209,17 @@ va_dcl if (!lp_syslog_only()) #endif { - if (!dbf) - { - int oldumask = umask(022); - dbf = fopen(debugf,"w"); - umask(oldumask); - if (dbf) - setbuf(dbf,NULL); - else - return(0); - } + if (!dbf) { + int oldumask = umask(022); + dbf = fopen(debugf,"w"); + umask(oldumask); + if (dbf) { + setbuf(dbf,NULL); + } else { + errno = old_errno; + return(0); + } + } } #ifdef SYSLOG @@ -273,6 +276,8 @@ va_dcl check_log_size(); + errno = old_errno; + return(0); } -- cgit From a70d0fc26ff0eed6ab4adea1b17f2d184d133d05 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 10 Oct 1997 02:35:55 +0000 Subject: fixed the log wrapping bug. This is a very nasty bug that I think explains quite a few intermittent problems people have been having with Samba. It may be worth checking on other cases where errno can be overwritten by seemingly innocuous things (in this case a DEBUG() line) --- source/lib/util.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/source/lib/util.c b/source/lib/util.c index 7f785332e6a..459745b8b14 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -156,7 +156,7 @@ static void check_log_size(void) int maxlog; struct stat st; - if (debug_count++ < 100) return; + if (debug_count++ < 100 || getuid() != 0) return; maxlog = lp_max_log_size() * 1024; if (!dbf || maxlog <= 0) return; @@ -175,7 +175,6 @@ static void check_log_size(void) debug_count=0; } - /******************************************************************* write an debug message on the debugfile. This is called by the DEBUG macro @@ -190,7 +189,8 @@ va_dcl char *format_str; #endif va_list ap; - + int old_errno = errno; + if (stdout_logging) { #ifdef __STDC__ va_start(ap, format_str); @@ -200,6 +200,7 @@ va_dcl #endif vfprintf(dbf,format_str,ap); va_end(ap); + errno = old_errno; return(0); } @@ -207,16 +208,17 @@ va_dcl if (!lp_syslog_only()) #endif { - if (!dbf) - { - int oldumask = umask(022); - dbf = fopen(debugf,"w"); - umask(oldumask); - if (dbf) - setbuf(dbf,NULL); - else - return(0); - } + if (!dbf) { + int oldumask = umask(022); + dbf = fopen(debugf,"w"); + umask(oldumask); + if (dbf) { + setbuf(dbf,NULL); + } else { + errno = old_errno; + return(0); + } + } } #ifdef SYSLOG @@ -273,6 +275,8 @@ va_dcl check_log_size(); + errno = old_errno; + return(0); } -- cgit From 37a8a5c4c69f051fa1b60f85db1f0ea6360bbba2 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 11:52:09 +0000 Subject: corrected paragraph giving the impression that samba can be a domain master for multiple workgroups. --- docs/textdocs/BROWSING.txt | 150 +++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 74 deletions(-) diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt index d8362f15299..cb509647c7e 100644 --- a/docs/textdocs/BROWSING.txt +++ b/docs/textdocs/BROWSING.txt @@ -8,8 +8,8 @@ Summary: This describes how to configure Samba for improved browsing. OVERVIEW: ========= SMB networking provides a mechanism by which clients can access a list -of machines that are available within the network. This list is called -the browse list and is heavily used by all SMB clients. Configuration +of machines that are available within the network. This list is called +the browse list and is heavily used by all SMB clients. Configuration of SMB browsing has been problematic for some Samba users, hence this document. @@ -17,7 +17,7 @@ document. BROWSING ======== -Samba now fully supports browsing. The browsing is supported by nmbd +Samba now fully supports browsing. The browsing is supported by nmbd and is also controlled by options in the smb.conf file (see smb.conf(5)). Samba can act as a local browse master for a workgroup and the ability @@ -28,10 +28,13 @@ Samba can also act as a domain master browser for a workgroup. This means that it will collate lists from local browse masters into a wide area network server list. In order for browse clients to resolve the names they may find in this list, it is recommended that -both samba and your clients use a WINS server +both samba and your clients use a WINS server. Note that you should NOT set Samba to be the domain master for a -workgroup that has the same name as an NT Domain. +workgroup that has the same name as an NT Domain: on each wide area +network, you must only ever have one domain master browser per workgroup, +regardless of whether it is NT, Samba or any other type of domain master +that is providing this service. [Note that nmbd can be configured as a WINS server, but it is not necessary to specifically use samba as your WINS server. NTAS can @@ -48,10 +51,10 @@ Samba becomes a part of. Samba also has a useful option for a Samba server to offer itself for browsing on another subnet. It is recommended that this option is only used for 'unusual' purposes: announcements over the internet, for -example. See "remote announce" in the smb.conf man page. +example. See "remote announce" in the smb.conf man page. If something doesn't work then hopefully the log.nmb file will -help you track down the problem. Try a debug level of 2 or 3 for +help you track down the problem. Try a debug level of 2 or 3 for finding problems. Note that if it doesn't work for you, then you should still be able to @@ -59,14 +62,14 @@ type the server name as \\SERVER in filemanager then hit enter and filemanager should display the list of available shares. Some people find browsing fails because they don't have the global -"guest account" set to a valid account. Remember that the IPC$ +"guest account" set to a valid account. Remember that the IPC$ connection that lists the shares is done as guest, and thus you must have a valid guest account. Also, a lot of people are getting bitten by the problem of too many -parameters on the command line of nmbd in inetd.conf. This trick is to +parameters on the command line of nmbd in inetd.conf. This trick is to not use spaces between the option and the parameter (eg: -d2 instead -of -d 2), and to not use the -B and -N options. New versions of nmbd +of -d 2), and to not use the -B and -N options. New versions of nmbd are now far more likely to correctly find your broadcast and network addess, so in most cases these aren't needed. @@ -74,23 +77,24 @@ The other big problem people have is that their broadcast address, netmask or IP address is wrong (specified with the "interfaces" option in smb.conf) + BROWSING ACROSS SUBNETS ======================= With the release of Samba 1.9.17(alpha1 and above) Samba has been updated to enable it to support the replication of browse lists -across subnet boundaries. New code and options have been added to -achieve this. This section describes how to set this feature up +across subnet boundaries. New code and options have been added to +achieve this. This section describes how to set this feature up in different settings. -To see browse lists that span TCP/IP subnets (ie. networks separated +To see browse lists that span TCP/IP subnets (ie. networks separated by routers that don't pass broadcast traffic) you must set up at least -one WINS server. The WINS server acts as a DNS for NetBIOS names, allowing +one WINS server. The WINS server acts as a DNS for NetBIOS names, allowing NetBIOS name to IP address translation to be done by doing a direct -query of the WINS server. This is done via a directed UDP packet on -port 137 to the WINS server machine. The reason for a WINS server is +query of the WINS server. This is done via a directed UDP packet on +port 137 to the WINS server machine. The reason for a WINS server is that by default, all NetBIOS name to IP address translation is done -by broadcasts from the querying machine. This means that machines +by broadcasts from the querying machine. This means that machines on one subnet will not be able to resolve the names of machines on another subnet without using a WINS server. @@ -104,7 +108,7 @@ How does cross subnet browsing work ? ===================================== Cross subnet browsing is a complicated dance, containing multiple -moving parts. It has taken Microsoft several years to get the code +moving parts. It has taken Microsoft several years to get the code that achieves this correct, and Samba lags behind in some areas. However, with the 1.9.17 release, Samba is capable of cross subnet browsing when configured correctly. @@ -127,38 +131,38 @@ Consider a network set up as follows : (WINS) Consisting of 3 subnets (1, 2, 3) conneted by two routers -(R1, R2) - these do not pass broadcasts. Subnet 1 has 5 machines -on it, subnet 2 has 4 machines, subnet 3 has 4 machines. Assume +(R1, R2) - these do not pass broadcasts. Subnet 1 has 5 machines +on it, subnet 2 has 4 machines, subnet 3 has 4 machines. Assume for the moment that all these machines are configured to be in the -same workgroup (for simplicities sake). Machine N1_C on subnet 1 -is configured as Domain Master Browser (ie. it will collate the -browse lists for the workgroup). Machine N2_D is configured as +same workgroup (for simplicities sake). Machine N1_C on subnet 1 +is configured as Domain Master Browser (ie. it will collate the +browse lists for the workgroup). Machine N2_D is configured as WINS server and all the other machines are configured to register their NetBIOS names with it. As all these machines are booted up, elections for master browsers -will take place on each of the three subnets. Assume that machine +will take place on each of the three subnets. Assume that machine N1_C wins on subnet 1, N2_B wins on subnet 2, and N3_D wins on subnet 3 - these machines are known as local master browsers for -their particular subnet. N1_C has an advantage in winning as the +their particular subnet. N1_C has an advantage in winning as the local master browser on subnet 1 as it is set up as Domain Master Browser. On each of the three networks, machines that are configured to offer sharing services will broadcast that they are offering -these services. The local master browser on each subnet will +these services. The local master browser on each subnet will receive these broadcasts and keep a record of the fact that -the machine is offering a service. This list of records is -the basis of the browse list. For this case, assume that +the machine is offering a service. This list of records is +the basis of the browse list. For this case, assume that all the machines are configured to offer services so all machines will be on the browse list. For each network, the local master browser on that network is considered 'authoritative' for all the names it receives via -local broadcast. This is because a machine seen by the local +local broadcast. This is because a machine seen by the local master browser via a local broadcast must be on the same network as the local master browser and thus is a 'trusted' -and 'verifiable' resource. Machines on other networks that +and 'verifiable' resource. Machines on other networks that the local master browsers learn about when collating their browse lists have not been directly seen - these records are called 'non-authoritative'. @@ -178,21 +182,21 @@ Subnet3 N3_D N3_A, N3_B, N3_C, N3_D Note that at this point all the subnets are separate, no machine is seen across any of the subnets. -Now examine subnet 2. As soon as N2_B has become the local +Now examine subnet 2. As soon as N2_B has become the local master browser it looks for a Domain master browser to synchronize -its browse list with. It does this by querying the WINS server +its browse list with. It does this by querying the WINS server (N2_D) for the IP address associated with the NetBIOS name -WORKGROUP<1B>. This name was registerd by the Domain master +WORKGROUP<1B>. This name was registerd by the Domain master browser (N1_C) with the WINS server as soon as it was booted. Once N2_B knows the address of the Domain master browser it tells it that is the local master browser for subnet 2 by sending a MasterAnnouncement packet as a UDP port 138 packet. -It then synchronizes with it by doing a NetServerEnum2 call. This +It then synchronizes with it by doing a NetServerEnum2 call. This tells the Domain Master Browser to send it all the server -names it knows about. Once the domain master browser receives +names it knows about. Once the domain master browser receives the MasterAnnouncement packet it schedules a synchronization -request to the sender of that packet. After both synchronizations +request to the sender of that packet. After both synchronizations are done the browse lists look like : Subnet Browse Master List @@ -212,10 +216,10 @@ subnets 1 or 2 will see all the servers on both, users on subnet 3 will still only see the servers on their own subnet. The same sequence of events that occured for N2_B now occurs -for the local master browser on subnet 3 (N3_D). When it +for the local master browser on subnet 3 (N3_D). When it synchronizes browse lists with the domain master browser (N1_A) it gets both the server entries on subnet 1, and those on -subnet 2. After N3_D has synchronized with N1_C and vica-versa +subnet 2. After N3_D has synchronized with N1_C and vica-versa the browse lists look like. Subnet Browse Master List @@ -239,7 +243,7 @@ subnet 2 will still only see the servers on subnets 1 and 2, but not 3. Finally, the local master browser for subnet 2 (N2_B) will sync again with the domain master browser (N1_C) and will recieve the missing -server entries. Finally - and as a steady state (if no machines +server entries. Finally - and as a steady state (if no machines are removed or shut off) the browse lists will look like : Subnet Browse Master List @@ -273,36 +277,36 @@ names will not be removed from the network neighbourhood lists. 3) If one of the fragments is cut off from the WINS server, it will only be able to access servers on its local subnet, by using subnet-isolated -broadcast NetBIOS name resolution. The effects are similar to that of +broadcast NetBIOS name resolution. The effects are similar to that of losing access to a DNS server. Setting up a WINS server ======================== Either a Samba machine or a Windows NT Server machine may be set up -as a WINS server. To set a Samba machine to be a WINS server you must +as a WINS server. To set a Samba machine to be a WINS server you must add the following option to the smb.conf file on the selected machine : in the [globals] section add the line wins support = yes Versions of Samba previous to 1.9.17 had this parameter default to -yes. If you have any older versions of Samba on your network it is +yes. If you have any older versions of Samba on your network it is strongly suggested you upgrade to 1.9.17 or above, or at the very least set the parameter to 'no' on all these machines. Machines with "wins support = yes" will keep a list of all NetBIOS names registered with them, acting as a DNS for NetBIOS names. -You should set up only ONE wins server. Do NOT set the +You should set up only ONE wins server. Do NOT set the "wins support = yes" option on more than one Samba server. To set up a Windows NT Server as a WINS server you need to set up -the WINS service - see your NT documentation for details. Note that +the WINS service - see your NT documentation for details. Note that Windows NT WINS Servers can replicate to each other, allowing more -than one to be set up in a complex subnet environment. As Microsoft +than one to be set up in a complex subnet environment. As Microsoft refuse to document these replication protocols Samba cannot currently -participate in these replications. It is possible in the future that +participate in these replications. It is possible in the future that a Samba->Samba WINS replication protocol may be defined, in which case more than one Samba machine could be set up as a WINS server but currently only one Samba server should have the "wins support = yes" @@ -310,10 +314,10 @@ parameter set. After the WINS server has been configured you must ensure that all machines participating on the network are configured with the address -of this WINS server. If your WINS server is a Samba machine, fill in +of this WINS server. If your WINS server is a Samba machine, fill in the Samba machine IP address in the "Primary WINS Server" field of the "Control Panel->Network->Protocols->TCP->WINS Server" dialogs -in Windows 95 or Windows NT. To tell a Samba server the IP address +in Windows 95 or Windows NT. To tell a Samba server the IP address of the WINS server add the following line to the [global] section of all smb.conf files : @@ -323,14 +327,14 @@ where <name or IP address> is either the DNS name of the WINS server machine or its IP address. Note that this line MUST NOT BE SET in the smb.conf file of the Samba -server acting as the WINS server itself. If you set both the +server acting as the WINS server itself. If you set both the "wins support = yes" option and the "wins server = <name>" option then nmbd will fail to start. There are two possible scenarios for setting up cross subnet browsing. The first details setting up cross subnet browsing on a network containing Windows 95, Samba and Windows NT machines that are not configured as -part of a Windows NT Domain. The second details setting up cross subnet +part of a Windows NT Domain. The second details setting up cross subnet browsing on networks that contain NT Domains. Setting up Browsing in a WORKGROUP @@ -340,25 +344,23 @@ To set up cross subnet browsing on a network containing machines in up to be in a WORKGROUP, not an NT Domain you need to set up one Samba server to be the Domain Master Browser (note that this is *NOT* the same as a Primary Domain Controller, although in an NT Domain the -same machine plays both roles). The role of a Domain master browser is +same machine plays both roles). The role of a Domain master browser is to collate the browse lists from local master browsers on all the -subnets that have a machine participating in the workgroup. Without +subnets that have a machine participating in the workgroup. Without one machine configured as a domain master browser each subnet would be an isolated workgroup, unable to see any machines on any other -subnet. It is the presense of a domain master browser that makes +subnet. It is the presense of a domain master browser that makes cross subnet browsing possible for a workgroup. In an WORKGROUP environment the domain master browser must be a Samba server, and there must only be one domain master browser per -workgroup name (although the same Samba server can act as Domain -master browser for multiple workgroup names). To set up a Samba -server as a domain master browser set the following option in the -[global] section of the smb.conf file : +workgroup name. To set up a Samba server as a domain master browser, +set the following option in the [global] section of the smb.conf file : domain master = yes The domain master browser should also preferrably be the local master -browser for its own subnet. In order to achieve this set the following +browser for its own subnet. In order to achieve this set the following options in the [global] section of the smb.conf file : domain master = yes @@ -371,9 +373,9 @@ server, if you require. Next, you should ensure that each of the subnets contains a machine that can act as a local master browser for the -workgroup. Any NT machine should be able to do this, as will +workgroup. Any NT machine should be able to do this, as will Windows 95 machines (although these tend to get rebooted more -often, so it's not such a good idea to use these). To make a +often, so it's not such a good idea to use these). To make a Samba server a local master browser set the following options in the [global] section of the smb.conf file : @@ -387,7 +389,7 @@ or they will war with each other over which is to be the local master browser. The "local master" parameter allows Samba to act as a local master -browser. The "preferred master" causes nmbd to force a browser +browser. The "preferred master" causes nmbd to force a browser election on startup and the "os level" parameter sets Samba high enough so that it should win any browser elections. @@ -413,7 +415,7 @@ browser NetBIOS name (DOMAIN<1B>) with WINS instead of the PDC. For subnets other than the one containing the Windows NT PDC you may set up Samba servers as local master browsers as -described. To make a Samba server a local master browser set +described. To make a Samba server a local master browser set the following options in the [global] section of the smb.conf file : @@ -424,8 +426,8 @@ file : If you wish to have a Samba server fight the election with machines on the same subnet you may set the "os level" parameter to lower -levels. By doing this you can tune the order of machines that -will become local master browsers if they are running. For +levels. By doing this you can tune the order of machines that +will become local master browsers if they are running. For more details on this see the section "FORCING SAMBA TO BE THE MASTER" below. @@ -444,17 +446,17 @@ FORCING SAMBA TO BE THE MASTER ============================== Who becomes the "master browser" is determined by an election process -using broadcasts. Each election packet contains a number of parameters +using broadcasts. Each election packet contains a number of parameters which determine what precedence (bias) a host should have in the -election. By default Samba uses a very low precedence and thus loses +election. By default Samba uses a very low precedence and thus loses elections to just about anyone else. If you want Samba to win elections then just set the "os level" global -option in smb.conf to a higher number. It defaults to 0. Using 34 +option in smb.conf to a higher number. It defaults to 0. Using 34 would make it win all elections over every other system (except other samba systems!) -A "os level" of 2 would make it beat WfWg and Win95, but not NTAS. A +A "os level" of 2 would make it beat WfWg and Win95, but not NTAS. A NTAS domain controller uses level 32. The maximum os level is 255 @@ -487,9 +489,9 @@ MAKING SAMBA THE DOMAIN MASTER ============================== The domain master is responsible for collating the browse lists of -multiple subnets so that browsing can occur between subnets. You can +multiple subnets so that browsing can occur between subnets. You can make samba act as the domain master by setting "domain master = yes" -in smb.conf. By default it will not be a domain master. +in smb.conf. By default it will not be a domain master. Note that you should NOT set Samba to be the domain master for a workgroup that has the same name as an NT Domain. @@ -526,13 +528,13 @@ b) when a client receives a domain-wide browse list, and a user attempts to access a host in that list, it will contact the WINS server to resolve the NetBIOS name of that host. as long as that host has registered its NetBIOS name with the same WINS server, the user will - be able to see that host. + be able to see that host. NOTE ABOUT BROADCAST ADDRESSES ============================== If your network uses a "0" based broadcast address (for example if it -ends in a 0) then you will strike problems. Windows for Workgroups +ends in a 0) then you will strike problems. Windows for Workgroups does not seem to support a 0's broadcast and you will probably find that browsing and name lookups won't work. @@ -540,7 +542,7 @@ that browsing and name lookups won't work. MULTIPLE INTERFACES =================== -Samba now supports machines with multiple network interfaces. If you +Samba now supports machines with multiple network interfaces. If you have multiple interfaces then you will need to use the "interfaces" -option in smb.conf to configure them. See smb.conf(5) for details. +option in smb.conf to configure them. See smb.conf(5) for details. -- cgit From d8d063d29b52697070efb182d573d519e13c2e53 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Fri, 10 Oct 1997 14:12:22 +0000 Subject: After generating some discussion, listening to the opinions, and thinking it over, I've decided to move the tree & list code into a subdirectory. CRH --- source/ubi_AVLtree.h | 340 ---------------------- source/ubi_BinTree.h | 745 ------------------------------------------------- source/ubi_SplayTree.h | 339 ---------------------- source/ubi_dLinkList.h | 163 ----------- 4 files changed, 1587 deletions(-) delete mode 100644 source/ubi_AVLtree.h delete mode 100644 source/ubi_BinTree.h delete mode 100644 source/ubi_SplayTree.h delete mode 100644 source/ubi_dLinkList.h diff --git a/source/ubi_AVLtree.h b/source/ubi_AVLtree.h deleted file mode 100644 index 27d84a2896d..00000000000 --- a/source/ubi_AVLtree.h +++ /dev/null @@ -1,340 +0,0 @@ -#ifndef ubi_AVLtree_H -#define ubi_AVLtree_H -/* ========================================================================== ** - * ubi_AVLtree.h - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module provides an implementation of AVL height balanced binary - * trees. (Adelson-Velskii, Landis 1962) - * - * This header file contains the basic AVL structure and pointer typedefs - * as well as the prototypes needed to access the functions in the AVL - * module ubi_AVLtree. The .c file implements the low-level height balancing - * routines that manage the AVL tree, plus all of the basic primops for - * adding, searching for, and deleting nodes. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * $Log: ubi_AVLtree.h,v $ - * Revision 1.1 1997/10/09 04:09:51 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.4 1997/07/26 04:36:23 crh - * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied - * on backwards with respect to node deletion. I did some more digging and - * discovered that I was not changing the balance values correctly in the - * single rotation functions. Double rotation was working correctly because - * the formula for changing the balance values is the same for insertion or - * deletion. Not so for single rotation. - * - * I have tested the fix by loading the tree with over 44 thousand names, - * deleting 2,629 of them (all those in which the second character is 'u') - * and then walking the tree recursively to verify that the balance factor of - * each node is correct. Passed. - * - * Thanks Andrew! - * - * Also: - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd - * hoped they would do (see the bottom of the header file). They work now. - * - * Revision 2.3 1997/06/03 05:22:07 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.2 1995/10/03 22:15:47 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:46:44 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/03/05 14:11:22 CRH - * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, - * and so includes all of the changes to that module. In addition, a bug in - * the node deletion process has been fixed. - * - * After rewriting the Locate() function in ubi_BinTree, I decided that it was - * time to overhaul this module. In the process, I discovered a bug related - * to node deletion. To fix the bug, I wrote function Debalance(). A quick - * glance will show that it is very similar to the Rebalance() function. In - * previous versions of this module, I tried to include the functionality of - * Debalance() within Rebalance(), with poor results. - * - * Revision 1.0 93/10/15 22:58:48 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================= ** - */ - -#include "ubi_BinTree.h" /* Base erg binary tree support. */ - -/* ------------------------------------------------------------------------- ** - * AVL Tree Node Structure: This structure defines the basic elements of - * the AVL tree nodes. In general you *SHOULD NOT PLAY WITH THESE - * FIELDS*! But, of course, I have to put the structure into this - * header so that you can use the structure as a building block. - * - * The fields are as follows: - * Link - An array of pointers. These pointers are manipulated by the - * BT and AVL routines, and indicate the left and right child - * nodes, plus the parent node. By keeping track of the parent - * pointer, we avoid the need for recursive routines or hand- - * tooled stacks to keep track of our path back to the root. - * The use of these pointers is subject to change without - * notice. - * gender - For tree rebalancing purposes, it is necessary that each node - * know whether it is the left or right child of its parent, or - * if it is the root. This information is stored in this field. - * balance - This field is also needed for AVL balancing purposes. It - * indicates which subtree of the current node is longer, or if - * the subtrees are, in fact, balanced with respect to each - * other. - * ------------------------------------------------------------------------- ** - */ - -typedef struct ubi_avlNodeStruct { - struct ubi_avlNodeStruct - *Link[3]; /* Normal Binary Tree Node type. */ - char gender; /* The node is either the RIGHT or LEFT child of its */ - /* parent, or is the root node. */ - char balance; /* In an AVL tree, each node is the root of a subtree */ - /* that may be balanced, or be one node longer to the */ - /* right or left. This field keeps track of the */ - /* balance value of each node. */ - } ubi_avlNode; /* Typedef'd name for an avl tree node. */ - -typedef ubi_avlNode *ubi_avlNodePtr; /* a Pointer to an AVL node */ - -/* -------------------------------------------------------------------------- ** - * Function prototypes. - * -------------------------------------------------------------------------- ** - */ - -ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: NodePtr - a pointer to a ubi_btNode structure to be - * initialized. - * Output: a pointer to the initialized ubi_avlNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, - ubi_avlNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_avlNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to - * the tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_avlNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, - ubi_avlNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree, after which the - * tree is rebalanced. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -int ubi_avlModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_avl... or ubi_bt, use ubi_tr... and select the tree - * type by including the appropriate module header. - */ - -#undef ubi_trNode -#undef ubi_trNodePtr -#define ubi_trNode ubi_avlNode -#define ubi_trNodePtr ubi_avlNodePtr - -#undef ubi_trInitNode -#define ubi_trInitNode( Np ) ubi_avlInitNode( (ubi_avlNodePtr)(Np) ) - -#undef ubi_trInsert -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_avlNodePtr *)(On) ) - -#undef ubi_trRemove -#define ubi_trRemove( Rp, Dn ) \ - ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Dn) ) - -#undef ubi_trLocate -#define ubi_trLocate( Rp, Ip, Op ) \ - (ubi_avlNodePtr)ubi_btLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#undef ubi_trFind -#define ubi_trFind( Rp, Ip ) \ - (ubi_avlNodePtr)ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#undef ubi_trNext -#define ubi_trNext( P ) (ubi_avlNodePtr)ubi_btNext( (ubi_btNodePtr)(P) ) - -#undef ubi_trPrev -#define ubi_trPrev( P ) (ubi_avlNodePtr)ubi_btPrev( (ubi_btNodePtr)(P) ) - -#undef ubi_trFirst -#define ubi_trFirst( P ) (ubi_avlNodePtr)ubi_btFirst( (ubi_btNodePtr)(P) ) - -#undef ubi_trLast -#define ubi_trLast( P ) (ubi_avlNodePtr)ubi_btLast( (ubi_btNodePtr)(P) ) - -#undef ubi_trFirstOf -#define ubi_trFirstOf( Rp, Ip, P ) \ - (ubi_avlNodePtr)ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#undef ubi_trLastOf -#define ubi_trLastOf( Rp, Ip, P ) \ - (ubi_avlNodePtr)ubi_btLastOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#undef ubi_trLeafNode -#define ubi_trLeafNode( Nd ) \ - (ubi_avlNodePtr)ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) - -#undef ubi_trModuleID -#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l ) - - -/* =========================== End ubi_AVLtree.h =========================== */ -#endif /* ubi_AVLtree_H */ diff --git a/source/ubi_BinTree.h b/source/ubi_BinTree.h deleted file mode 100644 index 1be8cba8778..00000000000 --- a/source/ubi_BinTree.h +++ /dev/null @@ -1,745 +0,0 @@ -#ifndef ubi_BinTree_H -#define ubi_BinTree_H -/* ========================================================================== ** - * ubi_BinTree.h - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height - * balancing, no restructuring. Still, a good tool for creating short, low- - * overhead sorted lists of things that need to be found in a hurry. - * - * In addition, this module provides a good basis for creating other types - * of binary tree handling modules. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_BinTree.h,v $ - * Revision 1.1 1997/10/09 04:09:52 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.4 1997/07/26 04:11:14 crh - * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE - * and ubi_trFALSE. - * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. - * + There used to be something called "ubi_TypeDefs.h". I got rid of it. - * + Added function ubi_btLeafNode(). - * - * Revision 2.3 1997/06/03 05:15:27 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. - * Also changed the interface to function InitTree(). See the comments - * for this function for more information. - * - * Revision 2.2 1995/10/03 22:00:40 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:43:46 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:00:33 CRH - * Revision 2.0 of this program includes the following changes: - * - * 1) A fix to a major typo in the RepaceNode() function. - * 2) The addition of the static function Border(). - * 3) The addition of the public functions FirstOf() and LastOf(), which - * use Border(). These functions are used with trees that allow - * duplicate keys. - * 4) A complete rewrite of the Locate() function. Locate() now accepts - * a "comparison" operator. - * 5) Overall enhancements to both code and comments. - * - * I decided to give this a new major rev number because the interface has - * changed. In particular, there are two new functions, and changes to the - * Locate() function. - * - * Revision 1.0 93/10/15 22:55:04 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================== ** - */ - -/* -------------------------------------------------------------------------- ** - * Macros and constants. - * - * General purpose: - * ubi_trTRUE - Boolean TRUE. - * ubi_trFALSE - Boolean FALSE. - * - * Flags used in the tree header: - * ubi_trOVERWRITE - This flag indicates that an existing node may be - * overwritten by a new node with a matching key. - * ubi_trDUPKEY - This flag indicates that the tree allows duplicate - * keys. If the tree does allow duplicates, the - * overwrite flag is ignored. - * - * Node link array index constants: (Each node has an array of three - * pointers. One to the left, one to the right, and one back to the - * parent.) - * LEFT - Left child pointer. - * PARENT - Parent pointer. - * RIGHT - Right child pointer. - * EQUAL - Synonym for PARENT. - * - * ubi_trCompOps: These values are used in the ubi_trLocate() function. - * ubi_trLT - request the first instance of the greatest key less than - * the search key. - * ubi_trLE - request the first instance of the greatest key that is less - * than or equal to the search key. - * ubi_trEQ - request the first instance of key that is equal to the - * search key. - * ubi_trGE - request the first instance of a key that is greater than - * or equal to the search key. - * ubi_trGT - request the first instance of the first key that is greater - * than the search key. - * -------------------------------------------------------------------------- ** - */ - -#define ubi_trTRUE 0xFF -#define ubi_trFALSE 0x00 - -#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ -#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ - -/* Pointer array index constants... */ -#define LEFT 0x00 -#define PARENT 0x01 -#define RIGHT 0x02 -#define EQUAL PARENT - -typedef enum { - ubi_trLT = 1, - ubi_trLE, - ubi_trEQ, - ubi_trGE, - ubi_trGT - } ubi_trCompOps; - -/* -------------------------------------------------------------------------- ** - * These three macros allow simple manipulation of pointer index values (LEFT, - * RIGHT, and PARENT). - * - * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C - * uses {negative, zero, positive} values to indicate - * {less than, equal to, greater than}. - * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, - * RIGHT} (opposite of Normalize()). Note: C comparison - * functions, such as strcmp(), return {negative, zero, - * positive} values, which are not necessarily {-1, 0, - * 1}. This macro uses the the ubi_btSgn() function to - * compensate. - * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) - * is left as is. - * -------------------------------------------------------------------------- ** - */ -#define Normalize(W) ((char)((W)-EQUAL)) -#define AbNormal(W) ((char)( EQUAL+((char)ubi_btSgn( (W) )) )) -#define RevWay(W) ((char)((W)==LEFT?RIGHT:((W)==RIGHT?LEFT:EQUAL))) - -/* -------------------------------------------------------------------------- ** - * These macros allow us to quickly read the values of the OVERWRITE and - * DUPlicate KEY bits of the tree root flags field. - * -------------------------------------------------------------------------- ** - */ -#define Dups_OK(A) ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) -#define Ovwt_OK(A) ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) - -/* -------------------------------------------------------------------------- ** - * Typedefs... - * - * ubi_trBool - Your typcial true or false... - * - * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to - * indicate a key that is being searched for within the tree. - * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), - * or ubi_trInsert() functions are called. - * -------------------------------------------------------------------------- ** - */ - -typedef unsigned char ubi_trBool; - -typedef void *ubi_btItemPtr; /* A pointer to data within a node. */ - -/* ------------------------------------------------------------------------- ** - * Binary Tree Node Structure: This structure defines the basic elements of - * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! - * But, of course, I have to put the structure into this header so that - * you can use it as a building block. - * - * The fields are as follows: - * Link - an array of pointers. These pointers are manipulated by - * the BT routines. The pointers indicate the left and right - * child nodes and the parent node. By keeping track of the - * parent pointer, we avoid the need for recursive routines or - * hand-tooled stacks to keep track of our path back to the - * root. The use of these pointers is subject to change without - * notice. - * gender - a one-byte field indicating whether the node is the RIGHT or - * LEFT child of its parent. If the node is the root of the - * tree, gender will be PARENT. - * ------------------------------------------------------------------------- ** - */ -typedef struct ubi_btNodeStruct { - struct ubi_btNodeStruct *Link[ 3 ]; - char gender; - } ubi_btNode; - -typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ - -/* ------------------------------------------------------------------------- ** - * The next three typedefs define standard function types used by the binary - * tree management routines. In particular: - * - * ubi_btCompFunc is a pointer to a comparison function. Comparison - * functions are passed an ubi_btItemPtr and an - * ubi_btNodePtr. They return a value that is (<0), 0, - * or (>0) to indicate that the Item is (respectively) - * "less than", "equal to", or "greater than" the Item - * contained within the node. (See ubi_btInitTree()). - * ubi_btActionRtn is a pointer to a function that may be called for each - * node visited when performing a tree traversal (see - * ubi_btTraverse()). The function will be passed two - * parameters: the first is a pointer to a node in the - * tree, the second is a generic pointer that may point to - * anything that you like. - * ubi_btKillNodeRtn is a pointer to a function that will deallocate the - * memory used by a node (see ubi_btKillTree()). Since - * memory management is left up to you, deallocation may - * mean anything that you want it to mean. Just remember - * that the tree *will* be destroyed and that none of the - * node pointers will be valid any more. - * ------------------------------------------------------------------------- ** - */ - -typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); - -typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); - -typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); - -/* -------------------------------------------------------------------------- ** - * Tree Root Structure: This structure gives us a convenient handle for - * accessing whole AVL trees. The fields are: - * root - A pointer to the root node of the AVL tree. - * count - A count of the number of nodes stored in the tree. - * cmp - A pointer to the comparison routine to be used when building or - * searching the tree. - * flags - A set of bit flags. Two flags are currently defined: - * - * ubi_trOVERWRITE - If set, this flag indicates that a new node should - * (bit 0x01) overwrite an old node if the two have identical - * keys (ie., the keys are equal). - * ubi_trDUPKEY - If set, this flag indicates that the tree is - * (bit 0x02) allowed to contain nodes with duplicate keys. - * - * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. - * - * All of these values are set when you initialize the root structure by - * calling ubi_trInitTree(). - * -------------------------------------------------------------------------- ** - */ - -typedef struct { - ubi_btNodePtr root; /* A pointer to the root node of the tree */ - unsigned long count; /* A count of the number of nodes in the tree */ - ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ - unsigned char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ - } ubi_btRoot; - -typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ - - -/* -------------------------------------------------------------------------- ** - * Function Prototypes. - */ - -long ubi_btSgn( long x ); - /* ------------------------------------------------------------------------ ** - * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. - * - * Input: x - a signed long integer value. - * - * Output: the "sign" of x, represented as follows: - * -1 == negative - * 0 == zero (no sign) - * 1 == positive - * - * Note: This utility is provided in order to facilitate the conversion - * of C comparison function return values into BinTree direction - * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the - * AbNormal() conversion macro! - * - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: a pointer to a ubi_btNode structure to be initialized. - * Output: a pointer to the initialized ubi_btNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - -ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, - ubi_btCompFunc CompFunc, - unsigned char Flags ); - /* ------------------------------------------------------------------------ ** - * Initialize the fields of a Tree Root header structure. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure to be - * initialized. - * CompFunc - a pointer to a comparison function that will be used - * whenever nodes in the tree must be compared against - * outside values. - * Flags - One bytes worth of flags. Flags include - * ubi_trOVERWRITE and ubi_trDUPKEY. See the header - * file for more info. - * - * Output: a pointer to the initialized ubi_btRoot structure (ie. the - * same value as RootPtr). - * - * Note: The interface to this function has changed from that of - * previous versions. The <Flags> parameter replaces two - * boolean parameters that had the same basic effect. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, - ubi_btNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ); - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ); - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_btLocate(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Next node in the - * tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "next" node in the tree, or NULL if P pointed - * to the "last" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Previous node in - * the tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "previous" node in the tree, or NULL if P - * pointed to the "first" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) First node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "first" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Last node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "last" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ); - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the first (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the first node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ); - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the last (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the last node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, - ubi_btActionRtn EachNode, - void *UserData ); - /* ------------------------------------------------------------------------ ** - * Traverse a tree in sorted order (non-recursively). At each node, call - * (*EachNode)(), passing a pointer to the current node, and UserData as the - * second parameter. - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the tree to be traversed. - * EachNode - a pointer to a function to be called at each node - * as the node is visited. - * UserData - a generic pointer that may point to anything that - * you choose. - * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, - ubi_btKillNodeRtn FreeNode ); - /* ------------------------------------------------------------------------ ** - * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot - * structure. Note that this function will return FALSE if either parameter - * is NULL. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the root of the tree to delete. - * FreeNode - a function that will be called for each node in the - * tree to deallocate the memory used by the node. - * - * Output: A boolean value. FALSE if either input parameter was NULL, else - * TRUE. - * - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); - /* ------------------------------------------------------------------------ ** - * Returns a pointer to a leaf node. - * - * Input: leader - Pointer to a node at which to start the descent. - * - * Output: A pointer to a leaf node selected in a somewhat arbitrary - * manner. - * - * Notes: I wrote this function because I was using splay trees as a - * database cache. The cache had a maximum size on it, and I - * needed a way of choosing a node to sacrifice if the cache - * became full. In a splay tree, less recently accessed nodes - * tend toward the bottom of the tree, meaning that leaf nodes - * are good candidates for removal. (I really can't think of - * any other reason to use this function.) - * + In a simple binary tree or an AVL tree, the most recently - * added nodes tend to be nearer the bottom, making this a *bad* - * way to choose which node to remove from the cache. - * + Randomizing the traversal order is probably a good idea. You - * can improve the randomization of leaf node selection by passing - * in pointers to nodes other than the root node each time. A - * pointer to any node in the tree will do. Of course, if you - * pass a pointer to a leaf node you'll get the same thing back. - * - * ------------------------------------------------------------------------ ** - */ - - -int ubi_btModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by - * including the appropriate module header. - */ - -#define ubi_trItemPtr ubi_btItemPtr - -#define ubi_trNode ubi_btNode -#define ubi_trNodePtr ubi_btNodePtr - -#define ubi_trRoot ubi_btRoot -#define ubi_trRootPtr ubi_btRootPtr - -#define ubi_trCompFunc ubi_btCompFunc -#define ubi_trActionRtn ubi_btActionRtn -#define ubi_trKillNodeRtn ubi_btKillNodeRtn - -#define ubi_trSgn( x ) ubi_btSgn( x ) - -#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) - -#define ubi_trInitTree( Rp, Cf, Fl ) \ - ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) - -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) - -#define ubi_trRemove( Rp, Dn ) \ - ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) - -#define ubi_trLocate( Rp, Ip, Op ) \ - ubi_btLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#define ubi_trFind( Rp, Ip ) \ - ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) - -#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) - -#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) - -#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) - -#define ubi_trFirstOf( Rp, Ip, P ) \ - ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#define ubi_trLastOf( Rp, Ip, P ) \ - ubi_btLastOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#define ubi_trTraverse( Rp, En, Ud ) \ - ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) - -#define ubi_trKillTree( Rp, Fn ) \ - ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) - -#define ubi_trLeafNode( Nd ) \ - ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) - -#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) - -/* ========================================================================== */ -#endif /* ubi_BinTree_H */ diff --git a/source/ubi_SplayTree.h b/source/ubi_SplayTree.h deleted file mode 100644 index 6a17a19ec4f..00000000000 --- a/source/ubi_SplayTree.h +++ /dev/null @@ -1,339 +0,0 @@ -#ifndef ubi_SplayTree_H -#define ubi_SplayTree_H -/* ========================================================================== ** - * ubi_SplayTree.h - * - * Copyright (C) 1993,1995 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module implements "splay" trees. Splay trees are binary trees - * that are rearranged (splayed) whenever a node is accessed. The - * splaying process *tends* to make the tree bushier (improves balance), - * and the nodes that are accessed most frequently *tend* to be closer to - * the top. - * - * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and - * Robert Tarjan. Journal of the Association for Computing - * Machinery Vol 32, No. 3, July 1985 pp. 652-686 - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_SplayTree.h,v $ - * Revision 1.1 1997/10/09 04:09:55 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.5 1997/07/26 04:15:46 crh - * + Cleaned up a few minor syntax annoyances that gcc discovered for me. - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * - * Revision 2.4 1997/06/03 05:22:56 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.3 1995/10/03 22:19:37 CRH - * Ubisized! - * Also, added the function ubi_sptSplay(). - * - * Revision 2.1 95/03/09 23:55:04 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:34:55 CRH - * This module was updated to match the interface changes made to the - * ubi_BinTree module. In particular, the interface to the Locate() function - * has changed. See ubi_BinTree for more information on changes and new - * functions. - * - * The revision number was also upped to match ubi_BinTree. - * - * - * Revision 1.0 93/10/15 22:59:36 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * Revision 0.0 93/04/21 23:07:13 CRH - * Initial version, written by Christopher R. Hertel. - * This module implements Splay Trees using the ubi_BinTree module as a basis. - * - * ========================================================================== ** - */ - -#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ - -/* ========================================================================== ** - * Function prototypes... - */ - -ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * splay tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ); - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ); - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_sptLocate(). - * ------------------------------------------------------------------------ ** - */ - -void ubi_sptSplay( ubi_btRootPtr RootPtr, - ubi_btNodePtr SplayMe ); - /* ------------------------------------------------------------------------ ** - * This function allows you to splay the tree at a given node, thus moving - * the node to the top of the tree. - * - * Input: - * RootPtr - a pointer to the header of the tree to be splayed. - * SplayMe - a pointer to a node within the tree. This will become - * the new root node. - * Output: None. - * - * Notes: This is an uncharacteristic function for this group of modules - * in that it provides access to the internal balancing routines, - * which would normally be hidden. - * Splaying the tree will not damage it (assuming that I've done - * *my* job), but there is overhead involved. I don't recommend - * that you use this function unless you understand the underlying - * Splay Tree principles involved. - * ------------------------------------------------------------------------ ** - */ - -int ubi_sptModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by - * including the appropriate module header. - */ - -#undef ubi_trInsert -#undef ubi_trRemove -#undef ubi_trLocate -#undef ubi_trFind -#undef ubi_trModuleID - -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) - -#define ubi_trRemove( Rp, Dn ) \ - ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) - -#define ubi_trLocate( Rp, Ip, Op ) \ - ubi_sptLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#define ubi_trFind( Rp, Ip ) \ - ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) - -/* ================================ The End ================================= */ -#endif /* ubi_SplayTree_H */ - - - - - diff --git a/source/ubi_dLinkList.h b/source/ubi_dLinkList.h deleted file mode 100644 index 8aafd99704e..00000000000 --- a/source/ubi_dLinkList.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef ubi_dLinkList_H -#define ubi_dLinkList_H -/* ========================================================================== ** - * ubi_dLinkList.h - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements simple doubly-linked lists. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_dLinkList.h,v $ - * Revision 1.1 1997/10/09 04:09:56 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 0.2 1997/10/08 03:08:16 crh - * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() - * macro, which was passing the wrong value for <After> to Insert(). - * - * Revision 0.1 1997/10/07 04:34:38 crh - * Initial Revision. - * - * - * ========================================================================== ** - */ - -#include <stdlib.h> - - -/* ========================================================================== ** - * Typedefs... - * - * ubi_dlNode - This is the basic node structure. - * ubi_dlNodePtr - Pointer to a node. - * ubi_dlList - This is the list header structure. - * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). - * - */ - -typedef struct ubi_dlListNode - { - struct ubi_dlListNode *Next; - struct ubi_dlListNode *Prev; - } ubi_dlNode; - -typedef ubi_dlNode *ubi_dlNodePtr; - -typedef struct - { - ubi_dlNodePtr Head; - ubi_dlNodePtr Tail; - unsigned long count; - } ubi_dlList; - -typedef ubi_dlList *ubi_dlListPtr; - -/* ========================================================================== ** - * Macros... - * - * ubi_dlAddHead - Add a new node at the head of the list. - * ubi_dlAddTail - Add a new node at the tail of the list. - * ubi_dlRemHead - Remove the node at the head of the list, if any. - * ubi_dlRemTail - Remove the node at the tail of the list, if any. - * ubi_dlFirst - Return a pointer to the first node in the list, if any. - * ubi_dlLast - Return a pointer to the last node in the list, if any. - * ubi_dlNext - Given a node, return a pointer to the next node. - * ubi_dlPrev - Given a node, return a pointer to the previous node. - */ - -#define ubi_dlAddHead( L, N ) ubi_dlInsert( (L), (N), NULL ) - -#define ubi_dlAddTail( L, N ) ubi_dlInsert( (L), (N), ((L)->Tail) ) - -#define ubi_dlRemHead( L ) ubi_dlRemove( (L), ((L)->Head) ) - -#define ubi_dlRemTail( L ) ubi_dlRemove( (L), ((L)->Tail) ) - -#define ubi_dlFirst( L ) ((L)->Head) - -#define ubi_dlLast( L ) ((L)->Tail) - -#define ubi_dlNext( N ) ((N)->Next) - -#define ubi_dlPrev( N ) ((N)->Prev) - - -/* ========================================================================== ** - * Function prototypes... - */ - -ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a doubly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, - ubi_dlNodePtr New, - ubi_dlNodePtr After ); - /* ------------------------------------------------------------------------ ** - * Insert a new node into the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the new node. - * After - NULL, or a pointer to a node that is already in the - * list. - * If NULL, then <New> will be added at the head of the - * list, else it will be added following <After>. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); - /* ------------------------------------------------------------------------ ** - * Remove a node from the list. - * - * Input: ListPtr - A pointer to the list from which <Old> is to be - * removed. - * Old - A pointer to the node that is to be removed from the - * list. - * - * Output: A pointer to the node that was removed (i.e., <Old>). - * - * ------------------------------------------------------------------------ ** - */ - - -/* ================================ The End ================================= */ -#endif /* ubi_dLinkList_H */ -- cgit From 6fffcff57d20690546a545ddd95a5d3d2c329715 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Fri, 10 Oct 1997 14:13:48 +0000 Subject: After generating some discussion, listening to the opinions, and thinking about it for a while, I've decided to move the tree & list code into a separate subdirectory. --- source/ubi_AVLtree.c | 699 -------------------------------- source/ubi_BinTree.c | 1042 ------------------------------------------------ source/ubi_SplayTree.c | 472 ---------------------- source/ubi_dLinkList.c | 152 ------- 4 files changed, 2365 deletions(-) delete mode 100644 source/ubi_AVLtree.c delete mode 100644 source/ubi_BinTree.c delete mode 100644 source/ubi_SplayTree.c delete mode 100644 source/ubi_dLinkList.c diff --git a/source/ubi_AVLtree.c b/source/ubi_AVLtree.c deleted file mode 100644 index 730392a472a..00000000000 --- a/source/ubi_AVLtree.c +++ /dev/null @@ -1,699 +0,0 @@ -/* ========================================================================== ** - * ubi_AVLtree.c - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module provides an implementation of AVL height balanced binary - * trees. (Adelson-Velskii, Landis 1962) - * - * This file implements the core of the height-balanced (AVL) tree management - * routines. The header file, ubi_AVLtree.h, contains function prototypes - * for all "exported" functions. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_AVLtree.c,v $ - * Revision 1.1 1997/10/09 04:09:51 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.4 1997/07/26 04:36:20 crh - * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied - * on backwards with respect to node deletion. I did some more digging and - * discovered that I was not changing the balance values correctly in the - * single rotation functions. Double rotation was working correctly because - * the formula for changing the balance values is the same for insertion or - * deletion. Not so for single rotation. - * - * I have tested the fix by loading the tree with over 44 thousand names, - * deleting 2,629 of them (all those in which the second character is 'u') - * and then walking the tree recursively to verify that the balance factor of - * each node is correct. Passed. - * - * Thanks Andrew! - * - * Also: - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd - * hoped they would do (see the bottom of the header file). They work now. - * - * Revision 2.3 1997/06/03 04:41:35 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.2 1995/10/03 22:16:01 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:45:59 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/03/05 14:10:51 CRH - * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, - * and so includes all of the changes to that module. In addition, a bug in - * the node deletion process has been fixed. - * - * After rewriting the Locate() function in ubi_BinTree, I decided that it was - * time to overhaul this module. In the process, I discovered a bug related - * to node deletion. To fix the bug, I wrote function Debalance(). A quick - * glance will show that it is very similar to the Rebalance() function. In - * previous versions of this module, I tried to include the functionality of - * Debalance() within Rebalance(), with poor results. - * - * Revision 1.0 93/10/15 22:58:56 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================= ** - */ - -#include "ubi_AVLtree.h" /* Header for THIS module. */ -#include <stdlib.h> /* Standard C definitions, etc. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_AVLtree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/09 04:09:51 $\n\ -\t$Author: crh $\n"; - -/* ========================================================================== ** - * The next set of functions are the AVL balancing routines. There are left - * and right, single and double rotations. The rotation routines handle the - * rotations and reconnect all tree pointers that might get confused by the - * rotations. A pointer to the new subtree root node is returned. - * - * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs - * are reversed. The same is true for L2 and R2. I'm sure that there is - * a clever way to reduce the amount of code by combining these functions, - * but it might involve additional overhead, and it would probably be a pain - * to read, debug, etc. - * -------------------------------------------------------------------------- ** - */ - -static ubi_avlNodePtr L1( ubi_avlNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Single rotate left. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp; - - tmp = p->Link[RIGHT]; - p->Link[RIGHT] = tmp->Link[LEFT]; - tmp->Link[LEFT] = p; - - tmp->Link[PARENT] = p->Link[PARENT]; - tmp->gender = p->gender; - if(tmp->Link[PARENT]) - (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; - p->Link[PARENT] = tmp; - p->gender = LEFT; - if( p->Link[RIGHT] ) - { - p->Link[RIGHT]->Link[PARENT] = p; - (p->Link[RIGHT])->gender = RIGHT; - } - p->balance -= Normalize( tmp->balance ); - (tmp->balance)--; - return( tmp ); - } /* L1 */ - -static ubi_avlNodePtr R1( ubi_avlNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Single rotate right. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp; - - tmp = p->Link[LEFT]; - p->Link[LEFT] = tmp->Link[RIGHT]; - tmp->Link[RIGHT] = p; - - tmp->Link[PARENT] = p->Link[PARENT]; - tmp->gender = p->gender; - if(tmp->Link[PARENT]) - (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; - p->Link[PARENT] = tmp; - p->gender = RIGHT; - if(p->Link[LEFT]) - { - p->Link[LEFT]->Link[PARENT] = p; - p->Link[LEFT]->gender = LEFT; - } - p->balance -= Normalize( tmp->balance ); - (tmp->balance)++; - return( tmp ); - } /* R1 */ - -static ubi_avlNodePtr L2( ubi_avlNodePtr tree ) - /* ------------------------------------------------------------------------ ** - * Double rotate left. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp, newroot; - - tmp = tree->Link[RIGHT]; - newroot = tmp->Link[LEFT]; - tmp->Link[LEFT] = newroot->Link[RIGHT]; - newroot->Link[RIGHT] = tmp; - tree->Link[RIGHT] = newroot->Link[LEFT]; - newroot->Link[LEFT] = tree; - - newroot->Link[PARENT] = tree->Link[PARENT]; - newroot->gender = tree->gender; - tree->Link[PARENT] = newroot; - tree->gender = LEFT; - tmp->Link[PARENT] = newroot; - tmp->gender = RIGHT; - - if( tree->Link[RIGHT] ) - { - tree->Link[RIGHT]->Link[PARENT] = tree; - tree->Link[RIGHT]->gender = RIGHT; - } - if( tmp->Link[LEFT] ) - { - tmp->Link[LEFT]->Link[PARENT] = tmp; - tmp->Link[LEFT]->gender = LEFT; - } - if(newroot->Link[PARENT]) - newroot->Link[PARENT]->Link[newroot->gender] = newroot; - - switch( newroot->balance ) - { - case LEFT : - tree->balance = EQUAL; tmp->balance = RIGHT; break; - case EQUAL: - tree->balance = EQUAL; tmp->balance = EQUAL; break; - case RIGHT: - tree->balance = LEFT; tmp->balance = EQUAL; break; - } - newroot->balance = EQUAL; - return( newroot ); - } /* L2 */ - -static ubi_avlNodePtr R2( ubi_avlNodePtr tree ) - /* ------------------------------------------------------------------------ ** - * Double rotate right. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp, newroot; - - tmp = tree->Link[LEFT]; - newroot = tmp->Link[RIGHT]; - tmp->Link[RIGHT] = newroot->Link[LEFT]; - newroot->Link[LEFT] = tmp; - tree->Link[LEFT] = newroot->Link[RIGHT]; - newroot->Link[RIGHT] = tree; - - newroot->Link[PARENT] = tree->Link[PARENT]; - newroot->gender = tree->gender; - tree->Link[PARENT] = newroot; - tree->gender = RIGHT; - tmp->Link[PARENT] = newroot; - tmp->gender = LEFT; - - if( tree->Link[LEFT] ) - { - tree->Link[LEFT]->Link[PARENT] = tree; - tree->Link[LEFT]->gender = LEFT; - } - if( tmp->Link[RIGHT] ) - { - tmp->Link[RIGHT]->Link[PARENT] = tmp; - tmp->Link[RIGHT]->gender = RIGHT; - } - if(newroot->Link[PARENT]) - newroot->Link[PARENT]->Link[newroot->gender] = newroot; - - switch( newroot->balance ) - { - case LEFT : - tree->balance = RIGHT; tmp->balance = EQUAL; break; - case EQUAL : - tree->balance = EQUAL; tmp->balance = EQUAL; break; - case RIGHT : - tree->balance = EQUAL; tmp->balance = LEFT; break; - } - newroot->balance = EQUAL; - return( newroot ); - } /* R2 */ - - -static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR ) - /* ------------------------------------------------------------------------ ** - * Adjust the balance value at node *p. If necessary, rotate the subtree - * rooted at p. - * - * Input: p - A pointer to the node to be adjusted. One of the - * subtrees of this node has changed height, so the - * balance value at this node must be adjusted, possibly - * by rotating the tree at this node. - * LorR - Indicates the TALLER subtree. - * - * Output: A pointer to the (possibly new) root node of the subtree. - * - * Notes: This function may be called after a node has been added *or* - * deleted, so LorR indicates the TALLER subtree. - * ------------------------------------------------------------------------ ** - */ - { - if( p->balance != LorR ) - p->balance += Normalize(LorR); - else - { - char tallerbal; /* Balance value of the root of the taller subtree of p. */ - - tallerbal = p->Link[LorR]->balance; - if( ( EQUAL == tallerbal ) || ( p->balance == tallerbal ) ) - p = ( (LEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */ - else - p = ( (LEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */ - } - return( p ); - } /* Adjust */ - -static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root, - ubi_avlNodePtr subtree, - char LorR ) - /* ------------------------------------------------------------------------ ** - * Rebalance the tree following an insertion. - * - * Input: Root - A pointer to the root node of the whole tree. - * subtree - A pointer to the node that has just gained a new - * child. - * LorR - Gender of the child that has just been gained. - * - * Output: A pointer to the (possibly new) root of the AVL tree. - * Rebalancing the tree moves nodes around a bit, so the node - * that *was* the root, may not be the root when we're finished. - * - * Notes: Rebalance() must walk up the tree from where we are (which is - * where the latest change occurred), rebalancing the subtrees - * along the way. The rebalancing operation can stop if the - * change at the current subtree root won't affect the rest of - * the tree. In the case of an addition, if a subtree root's - * balance becomes EQUAL, then we know that the height of that - * subtree has not changed, so we can exit. - * ------------------------------------------------------------------------ ** - */ - { - while( subtree ) - { - subtree = Adjust( subtree, LorR ); - if( PARENT == subtree->gender ) - return( subtree ); - if( EQUAL == subtree->balance ) - return( Root ); - LorR = subtree->gender; - subtree = subtree->Link[PARENT]; - } - return( Root ); - } /* Rebalance */ - -static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root, - ubi_avlNodePtr subtree, - char LorR ) - /* ------------------------------------------------------------------------ ** - * Rebalance the tree following a deletion. - * - * Input: Root - A pointer to the root node of the whole tree. - * subtree - A pointer to the node who's child has just "left the - * nest". - * LorR - Gender of the child that left. - * - * Output: A pointer to the (possibly new) root of the AVL tree. - * Rebalancing the tree moves nodes around a bit, so the node - * that *was* the root, may not be the root when we're finished. - * - * Notes: Debalance() is subtly different from Rebalance() (above) in - * two respects. - * * When it calls Adjust(), it passes the *opposite* of LorR. - * This is because LorR, as passed into Debalance() indicates - * the shorter subtree. As we move up the tree, LorR is - * assigned the gender of the node that we are leaving (i.e., - * the subtree that we just rebalanced). - * * We know that a subtree has not changed height if the - * balance becomes LEFT or RIGHT. This is the *opposite* of - * what happens in Rebalance(). - * ------------------------------------------------------------------------ ** - */ - { - while( subtree ) - { - subtree = Adjust( subtree, RevWay(LorR) ); - if( PARENT == subtree->gender ) - return( subtree ); - if( EQUAL != subtree->balance ) - return( Root ); - LorR = subtree->gender; - subtree = subtree->Link[PARENT]; - } - return( Root ); - } /* Debalance */ - - -/* -------------------------------------------------------------------------- ** - * The next two functions are used for general tree manipulation. They are - * each slightly different from their ubi_BinTree counterparts. - * -------------------------------------------------------------------------- ** - */ - -static void ReplaceNode( ubi_avlNodePtr *parent, - ubi_avlNodePtr oldnode, - ubi_avlNodePtr newnode ) - /* ------------------------------------------------------------------------ ** - * Remove node oldnode from the tree, replacing it with node newnode. - * - * Input: - * parent - A pointer to he parent pointer of the node to be - * replaced. <parent> may point to the Link[] field of - * a parent node, or it may indicate the root pointer at - * the top of the tree. - * oldnode - A pointer to the node that is to be replaced. - * newnode - A pointer to the node that is to be installed in the - * place of <*oldnode>. - * - * Notes: Don't forget to free oldnode. - * The only difference between this function and the ubi_bt - * version is that the node size is sizeof( ubi_avlNode ), not - * sizeof( ubi_btNode ). - * ------------------------------------------------------------------------ ** - */ - { - register int i; - register int avlNodeSize = sizeof( ubi_avlNode ); - - for( i = 0; i < avlNodeSize; i++ ) - ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - (*parent) = newnode; - - if(oldnode->Link[LEFT ] ) - (oldnode->Link[LEFT ])->Link[PARENT] = newnode; - if(oldnode->Link[RIGHT] ) - (oldnode->Link[RIGHT])->Link[PARENT] = newnode; - } /* ReplaceNode */ - -static void SwapNodes( ubi_btRootPtr RootPtr, - ubi_avlNodePtr Node1, - ubi_avlNodePtr Node2 ) - /* ------------------------------------------------------------------------ ** - * This function swaps two nodes in the tree. Node1 will take the place of - * Node2, and Node2 will fill in the space left vacant by Node 1. - * - * Input: - * RootPtr - pointer to the tree header structure for this tree. - * Node1 - \ - * > These are the two nodes which are to be swapped. - * Node2 - / - * - * Notes: - * This function does a three step swap, using a dummy node as a place - * holder. This function is used by ubi_avlRemove(). - * The only difference between this function and its ubi_bt counterpart - * is that the nodes are ubi_avlNodes, not ubi_btNodes. - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr *Parent; - ubi_avlNode dummy; - ubi_avlNodePtr dummy_p = &dummy; - - if( Node1->Link[PARENT] ) - Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, Node1, dummy_p ); - - if( Node2->Link[PARENT] ) - Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, Node2, Node1 ); - - if( dummy_p->Link[PARENT] ) - Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, dummy_p, Node2 ); - } /* SwapNodes */ - - -/* ========================================================================== ** - * Public, exported (ie. not static-ly declared) functions... - * -------------------------------------------------------------------------- ** - */ - -ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: NodePtr - pointer to a ubi_btNode structure to be - * initialized. - * Output: a pointer to the initialized ubi_avlNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - { - (void)ubi_btInitNode( (ubi_btNodePtr)NodePtr ); - NodePtr->balance = EQUAL; - return( NodePtr ); - } /* ubi_avlInitNode */ - -ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, - ubi_avlNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_avlNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to - * the tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_avlNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr OtherP; - - if( !(OldNode) ) OldNode = &OtherP; - if( ubi_btInsert( RootPtr, - (ubi_btNodePtr)NewNode, - ItemPtr, - (ubi_btNodePtr *)OldNode ) ) - { - if( (*OldNode) ) - NewNode->balance = (*OldNode)->balance; - else - { - NewNode->balance = EQUAL; - RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_avlNodePtr)RootPtr->root, - NewNode->Link[PARENT], - NewNode->gender ); - } - return( ubi_trTRUE ); - } - return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ - } /* ubi_avlInsert */ - -ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, - ubi_avlNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree, after which the - * tree is rebalanced. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, - *parentp; - - /* if the node has both left and right subtrees, then we have to swap - * it with another node. - */ - if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) - SwapNodes( RootPtr, DeadNode, ubi_trPrev( DeadNode ) ); - - /* The parent of the node to be deleted may be another node, or it may be - * the root of the tree. Since we're not sure, it's best just to have - * a pointer to the parent pointer, whatever it is. - */ - if( DeadNode->Link[PARENT] ) - parentp = (ubi_btNodePtr *) - &((DeadNode->Link[PARENT])->Link[(DeadNode->gender)]); - else - parentp = &( RootPtr->root ); - - /* Now link the parent to the only grand-child. Patch up the gender and - * such, and rebalance. - */ - if( EQUAL == DeadNode->balance ) - (*parentp) = NULL; - else - { - p = (ubi_btNodePtr)(DeadNode->Link[(DeadNode->balance)]); - p->Link[PARENT] = (ubi_btNodePtr)DeadNode->Link[PARENT]; - p->gender = DeadNode->gender; - (*parentp) = p; - } - RootPtr->root = (ubi_btNodePtr)Debalance( (ubi_avlNodePtr)RootPtr->root, - DeadNode->Link[PARENT], - DeadNode->gender ); - - (RootPtr->count)--; - return( DeadNode ); - } /* ubi_avlRemove */ - -int ubi_avlModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); - return( 1 ); - } - return( 0 ); - } /* ubi_avlModuleID */ - -/* ============================== The End ============================== */ diff --git a/source/ubi_BinTree.c b/source/ubi_BinTree.c deleted file mode 100644 index e6db1a4816c..00000000000 --- a/source/ubi_BinTree.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* ========================================================================== ** - * ubi_BinTree.c - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height - * balancing, no restructuring. Still, a good tool for creating short, low- - * overhead sorted lists of things that need to be found in a hurry. - * - * In addition, this module provides a good basis for creating other types - * of binary tree handling modules. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_BinTree.c,v $ - * Revision 1.1 1997/10/09 04:09:52 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.4 1997/07/26 04:11:10 crh - * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE - * and ubi_trFALSE. - * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. - * + There used to be something called "ubi_TypeDefs.h". I got rid of it. - * + Added function ubi_btLeafNode(). - * - * Revision 2.3 1997/06/03 05:16:17 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. - * Also changed the interface to function InitTree(). See the comments - * for this function for more information. - * - * Revision 2.2 1995/10/03 22:00:07 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:37:10 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:00:17 CRH - * Revision 2.0 of this program includes the following changes: - * - * 1) A fix to a major typo in the RepaceNode() function. - * 2) The addition of the static function Border(). - * 3) The addition of the public functions FirstOf() and LastOf(), which - * use Border(). These functions are used with trees that allow - * duplicate keys. - * 4) A complete rewrite of the Locate() function. Locate() now accepts - * a "comparison" operator. - * 5) Overall enhancements to both code and comments. - * - * I decided to give this a new major rev number because the interface has - * changed. In particular, there are two new functions, and changes to the - * Locate() function. - * - * Revision 1.0 93/10/15 22:44:59 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================== ** - */ - -#include "ubi_BinTree.h" /* Header for this module */ -#include <stdlib.h> /* Standard C definitions. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_BinTree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/09 04:09:52 $\n\ -\t$Author: crh $\n"; - -/* ========================================================================== ** - * Internal (private) functions. - */ - -static ubi_btNodePtr qFind( ubi_btCompFunc cmp, - ubi_btItemPtr FindMe, - register ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for a node - * matching a specific key. It is called "qFind()" because it is - * faster that TreeFind (below). - * - * Input: - * cmp - a pointer to the tree's comparison function. - * FindMe - a pointer to the key value for which to search. - * p - a pointer to the starting point of the search. <p> - * is considered to be the root of a subtree, and only - * the subtree will be searched. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. - * ------------------------------------------------------------------------ ** - */ - { - char tmp; - - while( p && (( tmp = AbNormal((*cmp)(FindMe, p)) ) != EQUAL) ) - p = p->Link[tmp]; - - return( p ); - } /* qFind */ - -static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, - ubi_btNodePtr p, - ubi_btNodePtr *parentp, - char *gender, - ubi_btCompFunc CmpFunc ) - /* ------------------------------------------------------------------------ ** - * TreeFind() searches a tree for a given value (findme). It will return a - * pointer to the target node, if found, or NULL if the target node was not - * found. - * - * TreeFind() also returns, via parameters, a pointer to the parent of the - * target node, and a LEFT or RIGHT value indicating which child of the - * parent is the target node. *If the target is not found*, then these - * values indicate the place at which the target *should be found*. This - * is useful when inserting a new node into a tree or searching for nodes - * "near" the target node. - * - * The parameters are: - * - * findme - is a pointer to the key information to be searched for. - * p - points to the root of the tree to be searched. - * parentp - will return a pointer to a pointer to the !parent! of the - * target node, which can be especially usefull if the target - * was not found. - * gender - returns LEFT or RIGHT to indicate which child of *parentp - * was last searched. - * CmpFunc - points to the comparison function. - * - * This function is called by ubi_btLocate() and ubi_btInsert(). - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr tmp_p = p; - ubi_btNodePtr tmp_pp = NULL; - char tmp_sex = EQUAL; - char tmp_cmp; - - while( tmp_p && (EQUAL != (tmp_cmp = AbNormal((*CmpFunc)(findme, tmp_p)))) ) - { - tmp_pp = tmp_p; /* Keep track of previous node. */ - tmp_sex = tmp_cmp; /* Keep track of sex of child. */ - tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ - } - *parentp = tmp_pp; /* Return results. */ - *gender = tmp_sex; - return( tmp_p ); - } /* TreeFind */ - -static void ReplaceNode( ubi_btNodePtr *parent, - ubi_btNodePtr oldnode, - ubi_btNodePtr newnode ) - /* ------------------------------------------------------------------ * - * Remove node oldnode from the tree, replacing it with node newnode. - * - * Input: - * parent - A pointer to he parent pointer of the node to be - * replaced. <parent> may point to the Link[] field of - * a parent node, or it may indicate the root pointer at - * the top of the tree. - * oldnode - A pointer to the node that is to be replaced. - * newnode - A pointer to the node that is to be installed in the - * place of <*oldnode>. - * - * Notes: Don't forget to free oldnode. - * Also, this function used to have a really nasty typo - * bug. "oldnode" and "newnode" were swapped in the line - * that now reads: - * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - * Bleah! - * ------------------------------------------------------------------ * - */ - { - register int i; - register int btNodeSize = sizeof( ubi_btNode ); - - for( i = 0; i < btNodeSize; i++ ) /* Copy node internals to new node. */ - ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - (*parent) = newnode; /* Old node's parent points to new child. */ - /* Now tell the children about their new step-parent. */ - if( oldnode->Link[LEFT ] ) (oldnode->Link[LEFT ])->Link[PARENT] = newnode; - if( oldnode->Link[RIGHT] ) (oldnode->Link[RIGHT])->Link[PARENT] = newnode; - } /* ReplaceNode */ - -static void SwapNodes( ubi_btRootPtr RootPtr, - ubi_btNodePtr Node1, - ubi_btNodePtr Node2 ) - /* ------------------------------------------------------------------------ ** - * This function swaps two nodes in the tree. Node1 will take the place of - * Node2, and Node2 will fill in the space left vacant by Node 1. - * - * Input: - * RootPtr - pointer to the tree header structure for this tree. - * Node1 - \ - * > These are the two nodes which are to be swapped. - * Node2 - / - * - * Notes: - * This function does a three step swap, using a dummy node as a place - * holder. This function is used by ubi_btRemove(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr *Parent; - ubi_btNode dummy; - ubi_btNodePtr dummy_p = &dummy; - - /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ - if( Node1->Link[PARENT] ) - Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, Node1, dummy_p ); - - /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ - if( Node2->Link[PARENT] ) - Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, Node2, Node1 ); - - /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ - if( dummy_p->Link[PARENT] ) - Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, dummy_p, Node2 ); - } /* SwapNodes */ - -/* -------------------------------------------------------------------------- ** - * These routines allow you to walk through the tree, forwards or backwards. - */ - -static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, - register char whichway ) - /* ------------------------------------------------------------------------ ** - * Slide down the side of a subtree. - * - * Given a starting node, this function returns a pointer to the LEFT-, or - * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. - * - * Input: P - a pointer to a starting place. - * whichway - the direction (LEFT, RIGHT, or PARENT) in which to - * travel. - * Output: A pointer to a node that is either the root, or has no - * whichway-th child but is within the subtree of P. Note that - * the return value may be the same as P. The return value *will - * be* NULL if P is NULL. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr Q = NULL; - - while( P ) - { - Q = P; - P = P->Link[ whichway ]; - } - return( Q ); - } /* SubSlide */ - -static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, - register char whichway ) - /* ------------------------------------------------------------------------ ** - * Given starting point p, return the (key order) next or preceeding node - * in the tree. - * - * Input: P - Pointer to our starting place node. - * whichway - the direction in which to travel to find the - * neighbor, i.e., the RIGHT neighbor or the LEFT - * neighbor. - * - * Output: A pointer to the neighboring node, or NULL if P was NULL. - * - * Notes: If whichway is PARENT, the results are unpredictable. - * ------------------------------------------------------------------------ ** - */ - { - if( P ) - { - if( P->Link[ whichway ] ) - return( SubSlide( P->Link[ whichway ], (char)RevWay(whichway) ) ); - else - while( P->Link[ PARENT ] ) - { - if( (P->Link[ PARENT ])->Link[ whichway ] == P ) - P = P->Link[ PARENT ]; - else - return( P->Link[ PARENT ] ); - } - } - return( NULL ); - } /* Neighbor */ - -static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_btNodePtr p, - char whichway ) - /* ------------------------------------------------------------------------ ** - * Given starting point p, which has a key value equal to *FindMe, locate - * the first (index order) node with the same key value. - * - * This function is useful in trees that have can have duplicate keys. - * For example, consider the following tree: - * Tree Traversal - * 2 If <p> points to the root and <whichway> is RIGHT, 3 - * / \ then the return value will be a pointer to the / \ - * 2 2 RIGHT child of the root node. The tree on 2 5 - * / / \ the right shows the order of traversal. / / \ - * 1 2 3 1 4 6 - * - * Input: RootPtr - Pointer to the tree root structure. - * FindMe - Key value for comparisons. - * p - Pointer to the starting-point node. - * whichway - the direction in which to travel to find the - * neighbor, i.e., the RIGHT neighbor or the LEFT - * neighbor. - * - * Output: A pointer to the first (index, or "traversal", order) node with - * a Key value that matches *FindMe. - * - * Notes: If whichway is PARENT, or if the tree does not allow duplicate - * keys, this function will return <p>. - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr q; - - /* Exit if there's nothing that can be done. */ - if( !Dups_OK( RootPtr ) || (PARENT == whichway) ) - return( p ); - - /* First, if needed, move up the tree. We need to get to the root of the - * subtree that contains all of the matching nodes. - */ - q = p->Link[PARENT]; - while( q && (EQUAL == AbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) - { - p = q; - q = p->Link[PARENT]; - } - - /* Next, move back down in the "whichway" direction. */ - q = p->Link[whichway]; - while( q ) - { - if( q = qFind( RootPtr->cmp, FindMe, q ) ) - { - p = q; - q = p->Link[whichway]; - } - } - return( p ); - } /* Border */ - - -/* ========================================================================== ** - * Exported utilities. - */ - -long ubi_btSgn( register long x ) - /* ------------------------------------------------------------------------ ** - * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. - * - * Input: x - a signed long integer value. - * - * Output: the "sign" of x, represented as follows: - * -1 == negative - * 0 == zero (no sign) - * 1 == positive - * - * Note: This utility is provided in order to facilitate the conversion - * of C comparison function return values into BinTree direction - * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the - * AbNormal() conversion macro! - * - * ------------------------------------------------------------------------ ** - */ - { - return( (x)?((x>0)?(1):(-1)):(0) ); - } /* ubi_btSgn */ - -ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: a pointer to a ubi_btNode structure to be initialized. - * Output: a pointer to the initialized ubi_btNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - { - NodePtr->Link[ LEFT ] = NULL; - NodePtr->Link[ PARENT ] = NULL; - NodePtr->Link[ RIGHT ] = NULL; - NodePtr->gender = EQUAL; - return( NodePtr ); - } /* ubi_btInitNode */ - -ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, - ubi_btCompFunc CompFunc, - unsigned char Flags ) - /* ------------------------------------------------------------------------ ** - * Initialize the fields of a Tree Root header structure. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure to be - * initialized. - * CompFunc - a pointer to a comparison function that will be used - * whenever nodes in the tree must be compared against - * outside values. - * Flags - One bytes worth of flags. Flags include - * ubi_trOVERWRITE and ubi_trDUPKEY. See the header - * file for more info. - * - * Output: a pointer to the initialized ubi_btRoot structure (ie. the - * same value as RootPtr). - * - * Note: The interface to this function has changed from that of - * previous versions. The <Flags> parameter replaces two - * boolean parameters that had the same basic effect. - * - * ------------------------------------------------------------------------ ** - */ - { - if( RootPtr ) - { - RootPtr->root = NULL; - RootPtr->count = 0L; - RootPtr->cmp = CompFunc; - RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; - } /* There are only two supported flags, and they are - * mutually exclusive. ubi_trDUPKEY takes precedence - * over ubi_trOVERWRITE. - */ - return( RootPtr ); - } /* ubi_btInitTree */ - -ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr OtherP, - parent = NULL; - char tmp; - - if( !(OldNode) ) /* If they didn't give us a pointer, supply our own. */ - OldNode = &OtherP; - - (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ - - /* Find a place for the new node. */ - *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); - - /* Now add the node to the tree... */ - if (!(*OldNode)) /* The easy one: we have a space for a new node! */ - { - if (!(parent)) - RootPtr->root = NewNode; - else - { - parent->Link[tmp] = NewNode; - NewNode->Link[PARENT] = parent; - NewNode->gender = tmp; - } - (RootPtr->count)++; - return( ubi_trTRUE ); - } - - /* If we reach this point, we know that a duplicate node exists. This - * section adds the node to the tree if duplicate keys are allowed. - */ - if( Dups_OK(RootPtr) ) /* Key exists, add duplicate */ - { - ubi_btNodePtr q; - - tmp = RIGHT; - q = (*OldNode); - *OldNode = NULL; - while( q ) - { - parent = q; - if( tmp == EQUAL ) tmp = RIGHT; - q = q->Link[tmp]; - if ( q ) - tmp = AbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); - } - parent->Link[tmp] = NewNode; - NewNode->Link[PARENT] = parent; - NewNode->gender = tmp; - (RootPtr->count)++; - return( ubi_trTRUE ); - } - - /* If we get to *this* point, we know that we are not allowed to have - * duplicate nodes, but our node keys match, so... may we replace the - * old one? - */ - if( Ovwt_OK(RootPtr) ) /* Key exists, we replace */ - { - if (!(parent)) - ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); - else - ReplaceNode( &(parent->Link[(*OldNode)->gender]), *OldNode, NewNode ); - return( ubi_trTRUE ); - } - - return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ - } /* ubi_btInsert */ - -ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, - ubi_btNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, - *parentp; - char tmp; - - /* if the node has both left and right subtrees, then we have to swap - * it with another node. The other node we choose will be the Prev()ious - * node, which is garunteed to have no RIGHT child. - */ - if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) - SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); - - /* The parent of the node to be deleted may be another node, or it may be - * the root of the tree. Since we're not sure, it's best just to have - * a pointer to the parent pointer, whatever it is. - */ - if (DeadNode->Link[PARENT]) - parentp = &((DeadNode->Link[PARENT])->Link[DeadNode->gender]); - else - parentp = &( RootPtr->root ); - - /* Now link the parent to the only grand-child and patch up the gender. */ - tmp = ((DeadNode->Link[LEFT])?LEFT:RIGHT); - - p = (DeadNode->Link[tmp]); - if( p ) - { - p->Link[PARENT] = DeadNode->Link[PARENT]; - p->gender = DeadNode->gender; - } - (*parentp) = p; - - /* Finished, reduce the node count and return. */ - (RootPtr->count)--; - return( DeadNode ); - } /* ubi_btRemove */ - -ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ) - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr p; - ubi_btNodePtr parent; - char whichkid; - - /* Start by searching for a matching node. */ - p = TreeFind( FindMe, - RootPtr->root, - &parent, - &whichkid, - RootPtr->cmp ); - - if( p ) /* If we have found a match, we can resolve as follows: */ - { - switch( CompOp ) - { - case ubi_trLT: /* It's just a jump to the left... */ - p = Border( RootPtr, FindMe, p, LEFT ); - return( Neighbor( p, LEFT ) ); - case ubi_trGT: /* ...and then a jump to the right. */ - p = Border( RootPtr, FindMe, p, RIGHT ); - return( Neighbor( p, RIGHT ) ); - } - p = Border( RootPtr, FindMe, p, LEFT ); - return( p ); - } - - /* Else, no match. */ - if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ - return( NULL ); /* ...forget it. */ - - /* We can still return a valid result for GT, GE, LE, and LT. - * <parent> points to a node with a value that is either just before or - * just after the target value. - * Remaining possibilities are LT and GT (including LE & GE). - */ - if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) - return( (LEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); - else - return( (RIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); - } /* ubi_btLocate */ - -ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_btLocate(). - * ------------------------------------------------------------------------ ** - */ - { - return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); - } /* ubi_btFind */ - -ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Next node in the - * tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "next" node in the tree, or NULL if P pointed - * to the "last" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - { - return( Neighbor( P, RIGHT ) ); - } /* ubi_btNext */ - -ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Previous node in - * the tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "previous" node in the tree, or NULL if P - * pointed to the "first" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - { - return( Neighbor( P, LEFT ) ); - } /* ubi_btPrev */ - -ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) First node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "first" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - { - return( SubSlide( P, LEFT ) ); - } /* ubi_btFirst */ - -ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Last node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "last" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - { - return( SubSlide( P, RIGHT ) ); - } /* ubi_btLast */ - -ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the first (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the first node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - { - /* If our starting point is invalid, return NULL. */ - if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) - return( NULL ); - return( Border( RootPtr, MatchMe, p, LEFT ) ); - } /* ubi_btFirstOf */ - -ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the last (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the last node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - { - /* If our starting point is invalid, return NULL. */ - if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) - return( NULL ); - return( Border( RootPtr, MatchMe, p, RIGHT ) ); - } /* ubi_btLastOf */ - -ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, - ubi_btActionRtn EachNode, - void *UserData ) - /* ------------------------------------------------------------------------ ** - * Traverse a tree in sorted order (non-recursively). At each node, call - * (*EachNode)(), passing a pointer to the current node, and UserData as the - * second parameter. - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the tree to be traversed. - * EachNode - a pointer to a function to be called at each node - * as the node is visited. - * UserData - a generic pointer that may point to anything that - * you choose. - * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - if( !(p = ubi_btFirst( RootPtr->root )) ) return( ubi_trFALSE ); - - while( p ) - { - EachNode( p, UserData ); - p = ubi_btNext( p ); - } - return( ubi_trTRUE ); - } /* ubi_btTraverse */ - -ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, - ubi_btKillNodeRtn FreeNode ) - /* ------------------------------------------------------------------------ ** - * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot - * structure. Note that this function will return FALSE if either parameter - * is NULL. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the root of the tree to delete. - * FreeNode - a function that will be called for each node in the - * tree to deallocate the memory used by the node. - * - * Output: A boolean value. FALSE if either input parameter was NULL, else - * TRUE. - * - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, q; - - if( !(RootPtr) || !(FreeNode) ) - return( ubi_trFALSE ); - - p = ubi_btFirst( RootPtr->root ); - while( p ) - { - q = p; - while( q->Link[RIGHT] ) - q = SubSlide( q->Link[RIGHT], LEFT ); - p = q->Link[PARENT]; - if( p ) - p->Link[ ((p->Link[LEFT] == q)?LEFT:RIGHT) ] = NULL; - FreeNode((void *)q); - } - - (void)ubi_btInitTree( RootPtr, - RootPtr->cmp, - RootPtr->flags ); - return( ubi_trTRUE ); - } /* ubi_btKillTree */ - -ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) - /* ------------------------------------------------------------------------ ** - * Returns a pointer to a leaf node. - * - * Input: leader - Pointer to a node at which to start the descent. - * - * Output: A pointer to a leaf node selected in a somewhat arbitrary - * manner. - * - * Notes: I wrote this function because I was using splay trees as a - * database cache. The cache had a maximum size on it, and I - * needed a way of choosing a node to sacrifice if the cache - * became full. In a splay tree, less recently accessed nodes - * tend toward the bottom of the tree, meaning that leaf nodes - * are good candidates for removal. (I really can't think of - * any other reason to use this function.) - * + In a simple binary tree or an AVL tree, the most recently - * added nodes tend to be nearer the bottom, making this a *bad* - * way to choose which node to remove from the cache. - * + Randomizing the traversal order is probably a good idea. You - * can improve the randomization of leaf node selection by passing - * in pointers to nodes other than the root node each time. A - * pointer to any node in the tree will do. Of course, if you - * pass a pointer to a leaf node you'll get the same thing back. - * - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr follower = NULL; - int whichway = LEFT; - - while( NULL != leader ) - { - follower = leader; - leader = follower->Link[ whichway ]; - if( NULL == leader ) - { - whichway = RevWay( whichway ); - leader = follower->Link[ whichway ]; - } - } - - return( follower ); - } /* ubi_btLeafNode */ - -int ubi_btModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - list[1] = NULL; - return( 1 ); - } - return( 0 ); - } /* ubi_btModuleID */ - - -/* ========================================================================== */ diff --git a/source/ubi_SplayTree.c b/source/ubi_SplayTree.c deleted file mode 100644 index d38e383d964..00000000000 --- a/source/ubi_SplayTree.c +++ /dev/null @@ -1,472 +0,0 @@ -/* ========================================================================== ** - * ubi_SplayTree.c - * - * Copyright (C) 1993-1995 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module implements "splay" trees. Splay trees are binary trees - * that are rearranged (splayed) whenever a node is accessed. The - * splaying process *tends* to make the tree bushier (improves balance), - * and the nodes that are accessed most frequently *tend* to be closer to - * the top. - * - * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and - * Robert Tarjan. Journal of the Association for Computing - * Machinery Vol 32, No. 3, July 1985 pp. 652-686 - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_SplayTree.c,v $ - * Revision 1.1 1997/10/09 04:09:54 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 2.5 1997/07/26 04:15:42 crh - * + Cleaned up a few minor syntax annoyances that gcc discovered for me. - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * - * Revision 2.4 1997/06/03 04:42:21 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.3 1995/10/03 22:19:07 CRH - * Ubisized! - * Also, added the function ubi_sptSplay(). - * - * Revision 2.1 95/03/09 23:54:42 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:34:46 CRH - * This module was updated to match the interface changes made to the - * ubi_BinTree module. In particular, the interface to the Locate() function - * has changed. See ubi_BinTree for more information on changes and new - * functions. - * - * The revision number was also upped to match ubi_BinTree. - * - * Revision 1.1 93/10/18 20:35:16 CRH - * I removed the hard-coded logical device names from the include file - * specifications. CRH - * - * Revision 1.0 93/10/15 23:00:15 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * Revision 0.1 93/04/25 22:03:32 CRH - * Simply changed the <exec/types.h> #include reference the .c file to - * use <stdlib.h> instead. The latter is portable, the former is not. - * - * Revision 0.0 93/04/21 23:05:52 CRH - * Initial version, written by Christopher R. Hertel. - * This module implements Splay Trees using the ubi_BinTree module as a basis. - * - * ========================================================================== ** - */ - -#include <stdlib.h> /* Defines NULL for us. */ -#include "ubi_SplayTree.h" /* Header for THIS module. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_SplayTree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/09 04:09:54 $\n\ -\t$Author: crh $\n"; - - -/* ========================================================================== ** - * Private functions... - */ - -static void Rotate( ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * This function performs a single rotation, moving node *p up one level - * in the tree. - * - * Input: p - a pointer to an ubi_btNode in a tree. - * - * Output: None. - * - * Notes: This implements a single rotation in either direction (left - * or right). This is the basic building block of all splay - * tree rotations. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr parentp; - ubi_btNodePtr tmp; - char way; - char revway; - - parentp = p->Link[PARENT]; /* Find parent. */ - - if( parentp ) /* If no parent, then we're already the root. */ - { - way = p->gender; - revway = RevWay(way); - tmp = p->Link[revway]; - - parentp->Link[way] = tmp; - if( tmp ) - { - tmp->Link[PARENT] = parentp; - tmp->gender = way; - } - - tmp = parentp->Link[PARENT]; - p->Link[PARENT] = tmp; - p->gender = parentp->gender; - if( tmp ) - tmp->Link[p->gender] = p; - - parentp->Link[PARENT] = p; - parentp->gender = revway; - p->Link[revway] = parentp; - } - } /* Rotate */ - -static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) - /* ------------------------------------------------------------------------ ** - * Move the node indicated by SplayWithMe to the root of the tree by - * splaying the tree. - * - * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. - * - * Output: A pointer to the root of the splay tree (i.e., the same as - * SplayWithMe). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr parent; - - while( (parent = SplayWithMe->Link[PARENT]) ) - { - if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ - Rotate( parent ); - else - { - if( EQUAL != parent->gender ) /* Zig-Zag */ - Rotate( SplayWithMe ); - } - Rotate( SplayWithMe ); /* Zig */ - } /* while */ - return( SplayWithMe ); - } /* Splay */ - -/* ========================================================================== ** - * Exported utilities. - */ - -ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * splay tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr OtherP; - - if( !(OldNode) ) - OldNode = &OtherP; - - if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) - { - RootPtr->root = Splay( NewNode ); - return( ubi_trTRUE ); - } - - /* Splay the unreplacable, duplicate keyed, unique, old node. */ - RootPtr->root = Splay( (*OldNode) ); - return( ubi_trFALSE ); - } /* ubi_sptInsert */ - -ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - (void)Splay( DeadNode ); /* Move dead node to root. */ - if( (p = DeadNode->Link[LEFT]) ) /* If left subtree exists... */ - { - ubi_btNodePtr q = DeadNode->Link[RIGHT]; - - p->Link[PARENT] = NULL; /* Left subtree node becomes root.*/ - p->gender = PARENT; - p = ubi_btLast( p ); /* Find rightmost left tree node..*/ - p->Link[RIGHT] = q; /* ...attach right tree. */ - if( q ) - q->Link[PARENT] = p; - RootPtr->root = Splay( p ); /* Resplay at p. */ - } - else - { - if( (p = DeadNode->Link[RIGHT]) ) /* No left, but right subtree... */ - { /* ...exists... */ - p->Link[PARENT] = NULL; /* Right subtree root becomes... */ - p->gender = PARENT; /* ...overall tree root. */ - RootPtr->root = p; - } - else - RootPtr->root = NULL; /* No subtrees => empty tree. */ - } - - (RootPtr->count)--; /* Decrement node count. */ - return( DeadNode ); /* Return pointer to pruned node. */ - } /* ubi_sptRemove */ - -ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ) - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - p = ubi_btLocate( RootPtr, FindMe, CompOp ); - if( p ) - RootPtr->root = Splay( p ); - return( p ); - } /* ubi_sptLocate */ - -ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_sptLocate(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - p = ubi_btFind( RootPtr, FindMe ); - if( p ) - RootPtr->root = Splay( p ); - return( p ); - } /* ubi_sptFind */ - -void ubi_sptSplay( ubi_btRootPtr RootPtr, - ubi_btNodePtr SplayMe ) - /* ------------------------------------------------------------------------ ** - * This function allows you to splay the tree at a given node, thus moving - * the node to the top of the tree. - * - * Input: - * RootPtr - a pointer to the header of the tree to be splayed. - * SplayMe - a pointer to a node within the tree. This will become - * the new root node. - * Output: None. - * - * Notes: This is an uncharacteristic function for this group of modules - * in that it provides access to the internal balancing routines, - * which would normally be hidden. - * Splaying the tree will not damage it (assuming that I've done - * *my* job), but there is overhead involved. I don't recommend - * that you use this function unless you understand the underlying - * Splay Tree principles involved. - * ------------------------------------------------------------------------ ** - */ - { - RootPtr->root = Splay( SplayMe ); - } /* ubi_sptSplay */ - -int ubi_sptModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); - return( 1 ); - } - return( 0 ); - } /* ubi_sptModuleID */ - -/* ================================ The End ================================= */ diff --git a/source/ubi_dLinkList.c b/source/ubi_dLinkList.c deleted file mode 100644 index 9c9ef3a73df..00000000000 --- a/source/ubi_dLinkList.c +++ /dev/null @@ -1,152 +0,0 @@ -/* ========================================================================== ** - * ubi_dLinkList.c - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements simple doubly-linked lists. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_dLinkList.c,v $ - * Revision 1.1 1997/10/09 04:09:55 crh - * This is my library of lists and trees. My hope is to replace all of the - * hard coded linked lists that are currently used in Samba with calls to - * these modules. This should make the code simpler, smaller, and (I hope) - * faster. The tree code, in particular, should speed up processing where - * large lists are involved. - * - * Chris -)----- - * - * Revision 0.2 1997/10/08 03:07:21 crh - * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() - * macro, which was passing the wrong value for <After> to Insert(). - * - * Revision 0.1 1997/10/07 04:34:07 crh - * Initial Revision. - * - * - * ========================================================================== ** - */ - -#include "ubi_dLinkList.h" - -/* ========================================================================== ** - * Functions... - */ - -ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a doubly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - { - ListPtr->Head = NULL; - ListPtr->Tail = NULL; - ListPtr->count = 0; - return( ListPtr ); - } /* ubi_dlInitList */ - -ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, - ubi_dlNodePtr New, - ubi_dlNodePtr After ) - /* ------------------------------------------------------------------------ ** - * Insert a new node into the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the new node. - * After - NULL, or a pointer to a node that is already in the - * list. - * If NULL, then <New> will be added at the head of the - * list, else it will be added following <After>. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - { - if( NULL == After ) - { - New->Next = ListPtr->Head; - New->Prev = NULL; - if( NULL != ListPtr->Head ) - ListPtr->Head->Prev = New; - else - ListPtr->Tail = New; - ListPtr->Head = New; - } - else - { - New->Next = After->Next; - New->Prev = After; - if( NULL != After->Next ) - After->Next->Prev = New; - else - ListPtr->Tail = New; - After->Next = New; - } - - ++(ListPtr->count); - - return( New ); - } /* ubi_dlInsert */ - -ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) - /* ------------------------------------------------------------------------ ** - * Remove a node from the list. - * - * Input: ListPtr - A pointer to the list from which <Old> is to be - * removed. - * Old - A pointer to the node that is to be removed from the - * list. - * - * Output: A pointer to the node that was removed (i.e., <Old>). - * - * ------------------------------------------------------------------------ ** - */ - { - if( NULL != Old ) - { - if( Old->Next ) - Old->Next->Prev = Old->Prev; - else - ListPtr->Tail = Old->Prev; - - if( Old->Prev ) - Old->Prev->Next = Old->Next; - else - ListPtr->Head = Old->Next; - - --(ListPtr->count); - } - - return( Old ); - } /* ubi_dlRemove */ - - -/* ================================ The End ================================= */ -- cgit From 3590a783338defa4ff1385b2d5bb095c5051ac82 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Fri, 10 Oct 1997 14:46:43 +0000 Subject: This is the ubiqx binary tree and linked list library. This library is being included as part of the Samba distribution. (Hurray!) --- source/ubiqx/ubi_AVLtree.c | 695 ++++++++++++++++++++++++++++ source/ubiqx/ubi_AVLtree.h | 336 ++++++++++++++ source/ubiqx/ubi_BinTree.c | 1038 ++++++++++++++++++++++++++++++++++++++++++ source/ubiqx/ubi_BinTree.h | 741 ++++++++++++++++++++++++++++++ source/ubiqx/ubi_SplayTree.c | 468 +++++++++++++++++++ source/ubiqx/ubi_SplayTree.h | 335 ++++++++++++++ source/ubiqx/ubi_dLinkList.c | 144 ++++++ source/ubiqx/ubi_dLinkList.h | 155 +++++++ 8 files changed, 3912 insertions(+) create mode 100644 source/ubiqx/ubi_AVLtree.c create mode 100644 source/ubiqx/ubi_AVLtree.h create mode 100644 source/ubiqx/ubi_BinTree.c create mode 100644 source/ubiqx/ubi_BinTree.h create mode 100644 source/ubiqx/ubi_SplayTree.c create mode 100644 source/ubiqx/ubi_SplayTree.h create mode 100644 source/ubiqx/ubi_dLinkList.c create mode 100644 source/ubiqx/ubi_dLinkList.h diff --git a/source/ubiqx/ubi_AVLtree.c b/source/ubiqx/ubi_AVLtree.c new file mode 100644 index 00000000000..73b8ece25bc --- /dev/null +++ b/source/ubiqx/ubi_AVLtree.c @@ -0,0 +1,695 @@ +/* ========================================================================== ** + * ubi_AVLtree.c + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This file implements the core of the height-balanced (AVL) tree management + * routines. The header file, ubi_AVLtree.h, contains function prototypes + * for all "exported" functions. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_AVLtree.c,v $ + * Revision 1.1 1997/10/10 14:46:36 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.4 1997/07/26 04:36:20 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 04:41:35 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:16:01 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:45:59 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:10:51 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:56 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "ubi_AVLtree.h" /* Header for THIS module. */ +#include <stdlib.h> /* Standard C definitions, etc. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_AVLtree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/10 14:46:36 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * The next set of functions are the AVL balancing routines. There are left + * and right, single and double rotations. The rotation routines handle the + * rotations and reconnect all tree pointers that might get confused by the + * rotations. A pointer to the new subtree root node is returned. + * + * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs + * are reversed. The same is true for L2 and R2. I'm sure that there is + * a clever way to reduce the amount of code by combining these functions, + * but it might involve additional overhead, and it would probably be a pain + * to read, debug, etc. + * -------------------------------------------------------------------------- ** + */ + +static ubi_avlNodePtr L1( ubi_avlNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp; + + tmp = p->Link[RIGHT]; + p->Link[RIGHT] = tmp->Link[LEFT]; + tmp->Link[LEFT] = p; + + tmp->Link[PARENT] = p->Link[PARENT]; + tmp->gender = p->gender; + if(tmp->Link[PARENT]) + (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; + p->Link[PARENT] = tmp; + p->gender = LEFT; + if( p->Link[RIGHT] ) + { + p->Link[RIGHT]->Link[PARENT] = p; + (p->Link[RIGHT])->gender = RIGHT; + } + p->balance -= Normalize( tmp->balance ); + (tmp->balance)--; + return( tmp ); + } /* L1 */ + +static ubi_avlNodePtr R1( ubi_avlNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Single rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp; + + tmp = p->Link[LEFT]; + p->Link[LEFT] = tmp->Link[RIGHT]; + tmp->Link[RIGHT] = p; + + tmp->Link[PARENT] = p->Link[PARENT]; + tmp->gender = p->gender; + if(tmp->Link[PARENT]) + (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; + p->Link[PARENT] = tmp; + p->gender = RIGHT; + if(p->Link[LEFT]) + { + p->Link[LEFT]->Link[PARENT] = p; + p->Link[LEFT]->gender = LEFT; + } + p->balance -= Normalize( tmp->balance ); + (tmp->balance)++; + return( tmp ); + } /* R1 */ + +static ubi_avlNodePtr L2( ubi_avlNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate left. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp, newroot; + + tmp = tree->Link[RIGHT]; + newroot = tmp->Link[LEFT]; + tmp->Link[LEFT] = newroot->Link[RIGHT]; + newroot->Link[RIGHT] = tmp; + tree->Link[RIGHT] = newroot->Link[LEFT]; + newroot->Link[LEFT] = tree; + + newroot->Link[PARENT] = tree->Link[PARENT]; + newroot->gender = tree->gender; + tree->Link[PARENT] = newroot; + tree->gender = LEFT; + tmp->Link[PARENT] = newroot; + tmp->gender = RIGHT; + + if( tree->Link[RIGHT] ) + { + tree->Link[RIGHT]->Link[PARENT] = tree; + tree->Link[RIGHT]->gender = RIGHT; + } + if( tmp->Link[LEFT] ) + { + tmp->Link[LEFT]->Link[PARENT] = tmp; + tmp->Link[LEFT]->gender = LEFT; + } + if(newroot->Link[PARENT]) + newroot->Link[PARENT]->Link[newroot->gender] = newroot; + + switch( newroot->balance ) + { + case LEFT : + tree->balance = EQUAL; tmp->balance = RIGHT; break; + case EQUAL: + tree->balance = EQUAL; tmp->balance = EQUAL; break; + case RIGHT: + tree->balance = LEFT; tmp->balance = EQUAL; break; + } + newroot->balance = EQUAL; + return( newroot ); + } /* L2 */ + +static ubi_avlNodePtr R2( ubi_avlNodePtr tree ) + /* ------------------------------------------------------------------------ ** + * Double rotate right. + * + * Input: p - Pointer to the root of a tree (possibly a subtree). + * Output: A pointer to the new root of the same subtree (now that node + * p has been moved). + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr tmp, newroot; + + tmp = tree->Link[LEFT]; + newroot = tmp->Link[RIGHT]; + tmp->Link[RIGHT] = newroot->Link[LEFT]; + newroot->Link[LEFT] = tmp; + tree->Link[LEFT] = newroot->Link[RIGHT]; + newroot->Link[RIGHT] = tree; + + newroot->Link[PARENT] = tree->Link[PARENT]; + newroot->gender = tree->gender; + tree->Link[PARENT] = newroot; + tree->gender = RIGHT; + tmp->Link[PARENT] = newroot; + tmp->gender = LEFT; + + if( tree->Link[LEFT] ) + { + tree->Link[LEFT]->Link[PARENT] = tree; + tree->Link[LEFT]->gender = LEFT; + } + if( tmp->Link[RIGHT] ) + { + tmp->Link[RIGHT]->Link[PARENT] = tmp; + tmp->Link[RIGHT]->gender = RIGHT; + } + if(newroot->Link[PARENT]) + newroot->Link[PARENT]->Link[newroot->gender] = newroot; + + switch( newroot->balance ) + { + case LEFT : + tree->balance = RIGHT; tmp->balance = EQUAL; break; + case EQUAL : + tree->balance = EQUAL; tmp->balance = EQUAL; break; + case RIGHT : + tree->balance = EQUAL; tmp->balance = LEFT; break; + } + newroot->balance = EQUAL; + return( newroot ); + } /* R2 */ + + +static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR ) + /* ------------------------------------------------------------------------ ** + * Adjust the balance value at node *p. If necessary, rotate the subtree + * rooted at p. + * + * Input: p - A pointer to the node to be adjusted. One of the + * subtrees of this node has changed height, so the + * balance value at this node must be adjusted, possibly + * by rotating the tree at this node. + * LorR - Indicates the TALLER subtree. + * + * Output: A pointer to the (possibly new) root node of the subtree. + * + * Notes: This function may be called after a node has been added *or* + * deleted, so LorR indicates the TALLER subtree. + * ------------------------------------------------------------------------ ** + */ + { + if( p->balance != LorR ) + p->balance += Normalize(LorR); + else + { + char tallerbal; /* Balance value of the root of the taller subtree of p. */ + + tallerbal = p->Link[LorR]->balance; + if( ( EQUAL == tallerbal ) || ( p->balance == tallerbal ) ) + p = ( (LEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */ + else + p = ( (LEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */ + } + return( p ); + } /* Adjust */ + +static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root, + ubi_avlNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following an insertion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node that has just gained a new + * child. + * LorR - Gender of the child that has just been gained. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Rebalance() must walk up the tree from where we are (which is + * where the latest change occurred), rebalancing the subtrees + * along the way. The rebalancing operation can stop if the + * change at the current subtree root won't affect the rest of + * the tree. In the case of an addition, if a subtree root's + * balance becomes EQUAL, then we know that the height of that + * subtree has not changed, so we can exit. + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, LorR ); + if( PARENT == subtree->gender ) + return( subtree ); + if( EQUAL == subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[PARENT]; + } + return( Root ); + } /* Rebalance */ + +static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root, + ubi_avlNodePtr subtree, + char LorR ) + /* ------------------------------------------------------------------------ ** + * Rebalance the tree following a deletion. + * + * Input: Root - A pointer to the root node of the whole tree. + * subtree - A pointer to the node who's child has just "left the + * nest". + * LorR - Gender of the child that left. + * + * Output: A pointer to the (possibly new) root of the AVL tree. + * Rebalancing the tree moves nodes around a bit, so the node + * that *was* the root, may not be the root when we're finished. + * + * Notes: Debalance() is subtly different from Rebalance() (above) in + * two respects. + * * When it calls Adjust(), it passes the *opposite* of LorR. + * This is because LorR, as passed into Debalance() indicates + * the shorter subtree. As we move up the tree, LorR is + * assigned the gender of the node that we are leaving (i.e., + * the subtree that we just rebalanced). + * * We know that a subtree has not changed height if the + * balance becomes LEFT or RIGHT. This is the *opposite* of + * what happens in Rebalance(). + * ------------------------------------------------------------------------ ** + */ + { + while( subtree ) + { + subtree = Adjust( subtree, RevWay(LorR) ); + if( PARENT == subtree->gender ) + return( subtree ); + if( EQUAL != subtree->balance ) + return( Root ); + LorR = subtree->gender; + subtree = subtree->Link[PARENT]; + } + return( Root ); + } /* Debalance */ + + +/* -------------------------------------------------------------------------- ** + * The next two functions are used for general tree manipulation. They are + * each slightly different from their ubi_BinTree counterparts. + * -------------------------------------------------------------------------- ** + */ + +static void ReplaceNode( ubi_avlNodePtr *parent, + ubi_avlNodePtr oldnode, + ubi_avlNodePtr newnode ) + /* ------------------------------------------------------------------------ ** + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. <parent> may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * The only difference between this function and the ubi_bt + * version is that the node size is sizeof( ubi_avlNode ), not + * sizeof( ubi_btNode ). + * ------------------------------------------------------------------------ ** + */ + { + register int i; + register int avlNodeSize = sizeof( ubi_avlNode ); + + for( i = 0; i < avlNodeSize; i++ ) + ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + (*parent) = newnode; + + if(oldnode->Link[LEFT ] ) + (oldnode->Link[LEFT ])->Link[PARENT] = newnode; + if(oldnode->Link[RIGHT] ) + (oldnode->Link[RIGHT])->Link[PARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_avlNodePtr Node1, + ubi_avlNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_avlRemove(). + * The only difference between this function and its ubi_bt counterpart + * is that the nodes are ubi_avlNodes, not ubi_btNodes. + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr *Parent; + ubi_avlNode dummy; + ubi_avlNodePtr dummy_p = &dummy; + + if( Node1->Link[PARENT] ) + Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + if( Node2->Link[PARENT] ) + Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + if( dummy_p->Link[PARENT] ) + Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); + else + Parent = (ubi_avlNodePtr *)&(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + + +/* ========================================================================== ** + * Public, exported (ie. not static-ly declared) functions... + * -------------------------------------------------------------------------- ** + */ + +ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: NodePtr - pointer to a ubi_btNode structure to be + * initialized. + * Output: a pointer to the initialized ubi_avlNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + (void)ubi_btInitNode( (ubi_btNodePtr)NodePtr ); + NodePtr->balance = EQUAL; + return( NodePtr ); + } /* ubi_avlInitNode */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_avlNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_avlNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_avlNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_avlNodePtr OtherP; + + if( !(OldNode) ) OldNode = &OtherP; + if( ubi_btInsert( RootPtr, + (ubi_btNodePtr)NewNode, + ItemPtr, + (ubi_btNodePtr *)OldNode ) ) + { + if( (*OldNode) ) + NewNode->balance = (*OldNode)->balance; + else + { + NewNode->balance = EQUAL; + RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_avlNodePtr)RootPtr->root, + NewNode->Link[PARENT], + NewNode->gender ); + } + return( ubi_trTRUE ); + } + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_avlInsert */ + +ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_avlNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. + */ + if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_trPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if( DeadNode->Link[PARENT] ) + parentp = (ubi_btNodePtr *) + &((DeadNode->Link[PARENT])->Link[(DeadNode->gender)]); + else + parentp = &( RootPtr->root ); + + /* Now link the parent to the only grand-child. Patch up the gender and + * such, and rebalance. + */ + if( EQUAL == DeadNode->balance ) + (*parentp) = NULL; + else + { + p = (ubi_btNodePtr)(DeadNode->Link[(DeadNode->balance)]); + p->Link[PARENT] = (ubi_btNodePtr)DeadNode->Link[PARENT]; + p->gender = DeadNode->gender; + (*parentp) = p; + } + RootPtr->root = (ubi_btNodePtr)Debalance( (ubi_avlNodePtr)RootPtr->root, + DeadNode->Link[PARENT], + DeadNode->gender ); + + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_avlRemove */ + +int ubi_avlModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_avlModuleID */ + +/* ============================== The End ============================== */ diff --git a/source/ubiqx/ubi_AVLtree.h b/source/ubiqx/ubi_AVLtree.h new file mode 100644 index 00000000000..be6fe032126 --- /dev/null +++ b/source/ubiqx/ubi_AVLtree.h @@ -0,0 +1,336 @@ +#ifndef ubi_AVLtree_H +#define ubi_AVLtree_H +/* ========================================================================== ** + * ubi_AVLtree.h + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module provides an implementation of AVL height balanced binary + * trees. (Adelson-Velskii, Landis 1962) + * + * This header file contains the basic AVL structure and pointer typedefs + * as well as the prototypes needed to access the functions in the AVL + * module ubi_AVLtree. The .c file implements the low-level height balancing + * routines that manage the AVL tree, plus all of the basic primops for + * adding, searching for, and deleting nodes. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * $Log: ubi_AVLtree.h,v $ + * Revision 1.1 1997/10/10 14:46:37 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.4 1997/07/26 04:36:23 crh + * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied + * on backwards with respect to node deletion. I did some more digging and + * discovered that I was not changing the balance values correctly in the + * single rotation functions. Double rotation was working correctly because + * the formula for changing the balance values is the same for insertion or + * deletion. Not so for single rotation. + * + * I have tested the fix by loading the tree with over 44 thousand names, + * deleting 2,629 of them (all those in which the second character is 'u') + * and then walking the tree recursively to verify that the balance factor of + * each node is correct. Passed. + * + * Thanks Andrew! + * + * Also: + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd + * hoped they would do (see the bottom of the header file). They work now. + * + * Revision 2.3 1997/06/03 05:22:07 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.2 1995/10/03 22:15:47 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:46:44 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/03/05 14:11:22 CRH + * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, + * and so includes all of the changes to that module. In addition, a bug in + * the node deletion process has been fixed. + * + * After rewriting the Locate() function in ubi_BinTree, I decided that it was + * time to overhaul this module. In the process, I discovered a bug related + * to node deletion. To fix the bug, I wrote function Debalance(). A quick + * glance will show that it is very similar to the Rebalance() function. In + * previous versions of this module, I tried to include the functionality of + * Debalance() within Rebalance(), with poor results. + * + * Revision 1.0 93/10/15 22:58:48 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================= ** + */ + +#include "ubi_BinTree.h" /* Base erg binary tree support. */ + +/* ------------------------------------------------------------------------- ** + * AVL Tree Node Structure: This structure defines the basic elements of + * the AVL tree nodes. In general you *SHOULD NOT PLAY WITH THESE + * FIELDS*! But, of course, I have to put the structure into this + * header so that you can use the structure as a building block. + * + * The fields are as follows: + * Link - An array of pointers. These pointers are manipulated by the + * BT and AVL routines, and indicate the left and right child + * nodes, plus the parent node. By keeping track of the parent + * pointer, we avoid the need for recursive routines or hand- + * tooled stacks to keep track of our path back to the root. + * The use of these pointers is subject to change without + * notice. + * gender - For tree rebalancing purposes, it is necessary that each node + * know whether it is the left or right child of its parent, or + * if it is the root. This information is stored in this field. + * balance - This field is also needed for AVL balancing purposes. It + * indicates which subtree of the current node is longer, or if + * the subtrees are, in fact, balanced with respect to each + * other. + * ------------------------------------------------------------------------- ** + */ + +typedef struct ubi_avlNodeStruct { + struct ubi_avlNodeStruct + *Link[3]; /* Normal Binary Tree Node type. */ + char gender; /* The node is either the RIGHT or LEFT child of its */ + /* parent, or is the root node. */ + char balance; /* In an AVL tree, each node is the root of a subtree */ + /* that may be balanced, or be one node longer to the */ + /* right or left. This field keeps track of the */ + /* balance value of each node. */ + } ubi_avlNode; /* Typedef'd name for an avl tree node. */ + +typedef ubi_avlNode *ubi_avlNodePtr; /* a Pointer to an AVL node */ + +/* -------------------------------------------------------------------------- ** + * Function prototypes. + * -------------------------------------------------------------------------- ** + */ + +ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: NodePtr - a pointer to a ubi_btNode structure to be + * initialized. + * Output: a pointer to the initialized ubi_avlNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, + ubi_avlNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_avlNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to + * the tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_avlNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, + ubi_avlNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree, after which the + * tree is rebalanced. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +int ubi_avlModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_avl... or ubi_bt, use ubi_tr... and select the tree + * type by including the appropriate module header. + */ + +#undef ubi_trNode +#undef ubi_trNodePtr +#define ubi_trNode ubi_avlNode +#define ubi_trNodePtr ubi_avlNodePtr + +#undef ubi_trInitNode +#define ubi_trInitNode( Np ) ubi_avlInitNode( (ubi_avlNodePtr)(Np) ) + +#undef ubi_trInsert +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_avlNodePtr *)(On) ) + +#undef ubi_trRemove +#define ubi_trRemove( Rp, Dn ) \ + ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Dn) ) + +#undef ubi_trLocate +#define ubi_trLocate( Rp, Ip, Op ) \ + (ubi_avlNodePtr)ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#undef ubi_trFind +#define ubi_trFind( Rp, Ip ) \ + (ubi_avlNodePtr)ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#undef ubi_trNext +#define ubi_trNext( P ) (ubi_avlNodePtr)ubi_btNext( (ubi_btNodePtr)(P) ) + +#undef ubi_trPrev +#define ubi_trPrev( P ) (ubi_avlNodePtr)ubi_btPrev( (ubi_btNodePtr)(P) ) + +#undef ubi_trFirst +#define ubi_trFirst( P ) (ubi_avlNodePtr)ubi_btFirst( (ubi_btNodePtr)(P) ) + +#undef ubi_trLast +#define ubi_trLast( P ) (ubi_avlNodePtr)ubi_btLast( (ubi_btNodePtr)(P) ) + +#undef ubi_trFirstOf +#define ubi_trFirstOf( Rp, Ip, P ) \ + (ubi_avlNodePtr)ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#undef ubi_trLastOf +#define ubi_trLastOf( Rp, Ip, P ) \ + (ubi_avlNodePtr)ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#undef ubi_trLeafNode +#define ubi_trLeafNode( Nd ) \ + (ubi_avlNodePtr)ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#undef ubi_trModuleID +#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l ) + + +/* =========================== End ubi_AVLtree.h =========================== */ +#endif /* ubi_AVLtree_H */ diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c new file mode 100644 index 00000000000..dc72f9bad3d --- /dev/null +++ b/source/ubiqx/ubi_BinTree.c @@ -0,0 +1,1038 @@ +/* ========================================================================== ** + * ubi_BinTree.c + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height + * balancing, no restructuring. Still, a good tool for creating short, low- + * overhead sorted lists of things that need to be found in a hurry. + * + * In addition, this module provides a good basis for creating other types + * of binary tree handling modules. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.c,v $ + * Revision 1.1 1997/10/10 14:46:38 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.4 1997/07/26 04:11:10 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:16:17 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:07 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:37:10 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:17 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:44:59 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Header for this module */ +#include <stdlib.h> /* Standard C definitions. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_BinTree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/10 14:46:38 $\n\ +\t$Author: crh $\n"; + +/* ========================================================================== ** + * Internal (private) functions. + */ + +static ubi_btNodePtr qFind( ubi_btCompFunc cmp, + ubi_btItemPtr FindMe, + register ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for a node + * matching a specific key. It is called "qFind()" because it is + * faster that TreeFind (below). + * + * Input: + * cmp - a pointer to the tree's comparison function. + * FindMe - a pointer to the key value for which to search. + * p - a pointer to the starting point of the search. <p> + * is considered to be the root of a subtree, and only + * the subtree will be searched. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. + * ------------------------------------------------------------------------ ** + */ + { + char tmp; + + while( p && (( tmp = AbNormal((*cmp)(FindMe, p)) ) != EQUAL) ) + p = p->Link[tmp]; + + return( p ); + } /* qFind */ + +static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, + ubi_btNodePtr p, + ubi_btNodePtr *parentp, + char *gender, + ubi_btCompFunc CmpFunc ) + /* ------------------------------------------------------------------------ ** + * TreeFind() searches a tree for a given value (findme). It will return a + * pointer to the target node, if found, or NULL if the target node was not + * found. + * + * TreeFind() also returns, via parameters, a pointer to the parent of the + * target node, and a LEFT or RIGHT value indicating which child of the + * parent is the target node. *If the target is not found*, then these + * values indicate the place at which the target *should be found*. This + * is useful when inserting a new node into a tree or searching for nodes + * "near" the target node. + * + * The parameters are: + * + * findme - is a pointer to the key information to be searched for. + * p - points to the root of the tree to be searched. + * parentp - will return a pointer to a pointer to the !parent! of the + * target node, which can be especially usefull if the target + * was not found. + * gender - returns LEFT or RIGHT to indicate which child of *parentp + * was last searched. + * CmpFunc - points to the comparison function. + * + * This function is called by ubi_btLocate() and ubi_btInsert(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr tmp_p = p; + ubi_btNodePtr tmp_pp = NULL; + char tmp_sex = EQUAL; + char tmp_cmp; + + while( tmp_p && (EQUAL != (tmp_cmp = AbNormal((*CmpFunc)(findme, tmp_p)))) ) + { + tmp_pp = tmp_p; /* Keep track of previous node. */ + tmp_sex = tmp_cmp; /* Keep track of sex of child. */ + tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ + } + *parentp = tmp_pp; /* Return results. */ + *gender = tmp_sex; + return( tmp_p ); + } /* TreeFind */ + +static void ReplaceNode( ubi_btNodePtr *parent, + ubi_btNodePtr oldnode, + ubi_btNodePtr newnode ) + /* ------------------------------------------------------------------ * + * Remove node oldnode from the tree, replacing it with node newnode. + * + * Input: + * parent - A pointer to he parent pointer of the node to be + * replaced. <parent> may point to the Link[] field of + * a parent node, or it may indicate the root pointer at + * the top of the tree. + * oldnode - A pointer to the node that is to be replaced. + * newnode - A pointer to the node that is to be installed in the + * place of <*oldnode>. + * + * Notes: Don't forget to free oldnode. + * Also, this function used to have a really nasty typo + * bug. "oldnode" and "newnode" were swapped in the line + * that now reads: + * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + * Bleah! + * ------------------------------------------------------------------ * + */ + { + register int i; + register int btNodeSize = sizeof( ubi_btNode ); + + for( i = 0; i < btNodeSize; i++ ) /* Copy node internals to new node. */ + ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; + (*parent) = newnode; /* Old node's parent points to new child. */ + /* Now tell the children about their new step-parent. */ + if( oldnode->Link[LEFT ] ) (oldnode->Link[LEFT ])->Link[PARENT] = newnode; + if( oldnode->Link[RIGHT] ) (oldnode->Link[RIGHT])->Link[PARENT] = newnode; + } /* ReplaceNode */ + +static void SwapNodes( ubi_btRootPtr RootPtr, + ubi_btNodePtr Node1, + ubi_btNodePtr Node2 ) + /* ------------------------------------------------------------------------ ** + * This function swaps two nodes in the tree. Node1 will take the place of + * Node2, and Node2 will fill in the space left vacant by Node 1. + * + * Input: + * RootPtr - pointer to the tree header structure for this tree. + * Node1 - \ + * > These are the two nodes which are to be swapped. + * Node2 - / + * + * Notes: + * This function does a three step swap, using a dummy node as a place + * holder. This function is used by ubi_btRemove(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr *Parent; + ubi_btNode dummy; + ubi_btNodePtr dummy_p = &dummy; + + /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ + if( Node1->Link[PARENT] ) + Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node1, dummy_p ); + + /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ + if( Node2->Link[PARENT] ) + Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, Node2, Node1 ); + + /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ + if( dummy_p->Link[PARENT] ) + Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); + else + Parent = &(RootPtr->root); + ReplaceNode( Parent, dummy_p, Node2 ); + } /* SwapNodes */ + +/* -------------------------------------------------------------------------- ** + * These routines allow you to walk through the tree, forwards or backwards. + */ + +static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, + register char whichway ) + /* ------------------------------------------------------------------------ ** + * Slide down the side of a subtree. + * + * Given a starting node, this function returns a pointer to the LEFT-, or + * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. + * + * Input: P - a pointer to a starting place. + * whichway - the direction (LEFT, RIGHT, or PARENT) in which to + * travel. + * Output: A pointer to a node that is either the root, or has no + * whichway-th child but is within the subtree of P. Note that + * the return value may be the same as P. The return value *will + * be* NULL if P is NULL. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr Q = NULL; + + while( P ) + { + Q = P; + P = P->Link[ whichway ]; + } + return( Q ); + } /* SubSlide */ + +static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, + register char whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, return the (key order) next or preceeding node + * in the tree. + * + * Input: P - Pointer to our starting place node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the neighboring node, or NULL if P was NULL. + * + * Notes: If whichway is PARENT, the results are unpredictable. + * ------------------------------------------------------------------------ ** + */ + { + if( P ) + { + if( P->Link[ whichway ] ) + return( SubSlide( P->Link[ whichway ], (char)RevWay(whichway) ) ); + else + while( P->Link[ PARENT ] ) + { + if( (P->Link[ PARENT ])->Link[ whichway ] == P ) + P = P->Link[ PARENT ]; + else + return( P->Link[ PARENT ] ); + } + } + return( NULL ); + } /* Neighbor */ + +static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_btNodePtr p, + char whichway ) + /* ------------------------------------------------------------------------ ** + * Given starting point p, which has a key value equal to *FindMe, locate + * the first (index order) node with the same key value. + * + * This function is useful in trees that have can have duplicate keys. + * For example, consider the following tree: + * Tree Traversal + * 2 If <p> points to the root and <whichway> is RIGHT, 3 + * / \ then the return value will be a pointer to the / \ + * 2 2 RIGHT child of the root node. The tree on 2 5 + * / / \ the right shows the order of traversal. / / \ + * 1 2 3 1 4 6 + * + * Input: RootPtr - Pointer to the tree root structure. + * FindMe - Key value for comparisons. + * p - Pointer to the starting-point node. + * whichway - the direction in which to travel to find the + * neighbor, i.e., the RIGHT neighbor or the LEFT + * neighbor. + * + * Output: A pointer to the first (index, or "traversal", order) node with + * a Key value that matches *FindMe. + * + * Notes: If whichway is PARENT, or if the tree does not allow duplicate + * keys, this function will return <p>. + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr q; + + /* Exit if there's nothing that can be done. */ + if( !Dups_OK( RootPtr ) || (PARENT == whichway) ) + return( p ); + + /* First, if needed, move up the tree. We need to get to the root of the + * subtree that contains all of the matching nodes. + */ + q = p->Link[PARENT]; + while( q && (EQUAL == AbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) + { + p = q; + q = p->Link[PARENT]; + } + + /* Next, move back down in the "whichway" direction. */ + q = p->Link[whichway]; + while( q ) + { + if( q = qFind( RootPtr->cmp, FindMe, q ) ) + { + p = q; + q = p->Link[whichway]; + } + } + return( p ); + } /* Border */ + + +/* ========================================================================== ** + * Exported utilities. + */ + +long ubi_btSgn( register long x ) + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + { + return( (x)?((x>0)?(1):(-1)):(0) ); + } /* ubi_btSgn */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + { + NodePtr->Link[ LEFT ] = NULL; + NodePtr->Link[ PARENT ] = NULL; + NodePtr->Link[ RIGHT ] = NULL; + NodePtr->gender = EQUAL; + return( NodePtr ); + } /* ubi_btInitNode */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + unsigned char Flags ) + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * + * ------------------------------------------------------------------------ ** + */ + { + if( RootPtr ) + { + RootPtr->root = NULL; + RootPtr->count = 0L; + RootPtr->cmp = CompFunc; + RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; + } /* There are only two supported flags, and they are + * mutually exclusive. ubi_trDUPKEY takes precedence + * over ubi_trOVERWRITE. + */ + return( RootPtr ); + } /* ubi_btInitTree */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP, + parent = NULL; + char tmp; + + if( !(OldNode) ) /* If they didn't give us a pointer, supply our own. */ + OldNode = &OtherP; + + (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ + + /* Find a place for the new node. */ + *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); + + /* Now add the node to the tree... */ + if (!(*OldNode)) /* The easy one: we have a space for a new node! */ + { + if (!(parent)) + RootPtr->root = NewNode; + else + { + parent->Link[tmp] = NewNode; + NewNode->Link[PARENT] = parent; + NewNode->gender = tmp; + } + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we reach this point, we know that a duplicate node exists. This + * section adds the node to the tree if duplicate keys are allowed. + */ + if( Dups_OK(RootPtr) ) /* Key exists, add duplicate */ + { + ubi_btNodePtr q; + + tmp = RIGHT; + q = (*OldNode); + *OldNode = NULL; + while( q ) + { + parent = q; + if( tmp == EQUAL ) tmp = RIGHT; + q = q->Link[tmp]; + if ( q ) + tmp = AbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); + } + parent->Link[tmp] = NewNode; + NewNode->Link[PARENT] = parent; + NewNode->gender = tmp; + (RootPtr->count)++; + return( ubi_trTRUE ); + } + + /* If we get to *this* point, we know that we are not allowed to have + * duplicate nodes, but our node keys match, so... may we replace the + * old one? + */ + if( Ovwt_OK(RootPtr) ) /* Key exists, we replace */ + { + if (!(parent)) + ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); + else + ReplaceNode( &(parent->Link[(*OldNode)->gender]), *OldNode, NewNode ); + return( ubi_trTRUE ); + } + + return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ + } /* ubi_btInsert */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, + *parentp; + char tmp; + + /* if the node has both left and right subtrees, then we have to swap + * it with another node. The other node we choose will be the Prev()ious + * node, which is garunteed to have no RIGHT child. + */ + if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) + SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); + + /* The parent of the node to be deleted may be another node, or it may be + * the root of the tree. Since we're not sure, it's best just to have + * a pointer to the parent pointer, whatever it is. + */ + if (DeadNode->Link[PARENT]) + parentp = &((DeadNode->Link[PARENT])->Link[DeadNode->gender]); + else + parentp = &( RootPtr->root ); + + /* Now link the parent to the only grand-child and patch up the gender. */ + tmp = ((DeadNode->Link[LEFT])?LEFT:RIGHT); + + p = (DeadNode->Link[tmp]); + if( p ) + { + p->Link[PARENT] = DeadNode->Link[PARENT]; + p->gender = DeadNode->gender; + } + (*parentp) = p; + + /* Finished, reduce the node count and return. */ + (RootPtr->count)--; + return( DeadNode ); + } /* ubi_btRemove */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + register ubi_btNodePtr p; + ubi_btNodePtr parent; + char whichkid; + + /* Start by searching for a matching node. */ + p = TreeFind( FindMe, + RootPtr->root, + &parent, + &whichkid, + RootPtr->cmp ); + + if( p ) /* If we have found a match, we can resolve as follows: */ + { + switch( CompOp ) + { + case ubi_trLT: /* It's just a jump to the left... */ + p = Border( RootPtr, FindMe, p, LEFT ); + return( Neighbor( p, LEFT ) ); + case ubi_trGT: /* ...and then a jump to the right. */ + p = Border( RootPtr, FindMe, p, RIGHT ); + return( Neighbor( p, RIGHT ) ); + } + p = Border( RootPtr, FindMe, p, LEFT ); + return( p ); + } + + /* Else, no match. */ + if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ + return( NULL ); /* ...forget it. */ + + /* We can still return a valid result for GT, GE, LE, and LT. + * <parent> points to a node with a value that is either just before or + * just after the target value. + * Remaining possibilities are LT and GT (including LE & GE). + */ + if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) + return( (LEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + else + return( (RIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); + } /* ubi_btLocate */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + { + return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); + } /* ubi_btFind */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, RIGHT ) ); + } /* ubi_btNext */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + { + return( Neighbor( P, LEFT ) ); + } /* ubi_btPrev */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, LEFT ) ); + } /* ubi_btFirst */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + { + return( SubSlide( P, RIGHT ) ); + } /* ubi_btLast */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, LEFT ) ); + } /* ubi_btFirstOf */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + { + /* If our starting point is invalid, return NULL. */ + if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) + return( NULL ); + return( Border( RootPtr, MatchMe, p, RIGHT ) ); + } /* ubi_btLastOf */ + +ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ) + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + if( !(p = ubi_btFirst( RootPtr->root )) ) return( ubi_trFALSE ); + + while( p ) + { + EachNode( p, UserData ); + p = ubi_btNext( p ); + } + return( ubi_trTRUE ); + } /* ubi_btTraverse */ + +ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ) + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Note that this function will return FALSE if either parameter + * is NULL. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: A boolean value. FALSE if either input parameter was NULL, else + * TRUE. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p, q; + + if( !(RootPtr) || !(FreeNode) ) + return( ubi_trFALSE ); + + p = ubi_btFirst( RootPtr->root ); + while( p ) + { + q = p; + while( q->Link[RIGHT] ) + q = SubSlide( q->Link[RIGHT], LEFT ); + p = q->Link[PARENT]; + if( p ) + p->Link[ ((p->Link[LEFT] == q)?LEFT:RIGHT) ] = NULL; + FreeNode((void *)q); + } + + (void)ubi_btInitTree( RootPtr, + RootPtr->cmp, + RootPtr->flags ); + return( ubi_trTRUE ); + } /* ubi_btKillTree */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr follower = NULL; + int whichway = LEFT; + + while( NULL != leader ) + { + follower = leader; + leader = follower->Link[ whichway ]; + if( NULL == leader ) + { + whichway = RevWay( whichway ); + leader = follower->Link[ whichway ]; + } + } + + return( follower ); + } /* ubi_btLeafNode */ + +int ubi_btModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + list[1] = NULL; + return( 1 ); + } + return( 0 ); + } /* ubi_btModuleID */ + + +/* ========================================================================== */ diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h new file mode 100644 index 00000000000..b4561a1f900 --- /dev/null +++ b/source/ubiqx/ubi_BinTree.h @@ -0,0 +1,741 @@ +#ifndef ubi_BinTree_H +#define ubi_BinTree_H +/* ========================================================================== ** + * ubi_BinTree.h + * + * Copyright (C) 1991-1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height + * balancing, no restructuring. Still, a good tool for creating short, low- + * overhead sorted lists of things that need to be found in a hurry. + * + * In addition, this module provides a good basis for creating other types + * of binary tree handling modules. + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_BinTree.h,v $ + * Revision 1.1 1997/10/10 14:46:39 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.4 1997/07/26 04:11:14 crh + * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE + * and ubi_trFALSE. + * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. + * + There used to be something called "ubi_TypeDefs.h". I got rid of it. + * + Added function ubi_btLeafNode(). + * + * Revision 2.3 1997/06/03 05:15:27 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. + * Also changed the interface to function InitTree(). See the comments + * for this function for more information. + * + * Revision 2.2 1995/10/03 22:00:40 CRH + * Ubisized! + * + * Revision 2.1 95/03/09 23:43:46 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:00:33 CRH + * Revision 2.0 of this program includes the following changes: + * + * 1) A fix to a major typo in the RepaceNode() function. + * 2) The addition of the static function Border(). + * 3) The addition of the public functions FirstOf() and LastOf(), which + * use Border(). These functions are used with trees that allow + * duplicate keys. + * 4) A complete rewrite of the Locate() function. Locate() now accepts + * a "comparison" operator. + * 5) Overall enhancements to both code and comments. + * + * I decided to give this a new major rev number because the interface has + * changed. In particular, there are two new functions, and changes to the + * Locate() function. + * + * Revision 1.0 93/10/15 22:55:04 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). + * + * ========================================================================== ** + */ + +/* -------------------------------------------------------------------------- ** + * Macros and constants. + * + * General purpose: + * ubi_trTRUE - Boolean TRUE. + * ubi_trFALSE - Boolean FALSE. + * + * Flags used in the tree header: + * ubi_trOVERWRITE - This flag indicates that an existing node may be + * overwritten by a new node with a matching key. + * ubi_trDUPKEY - This flag indicates that the tree allows duplicate + * keys. If the tree does allow duplicates, the + * overwrite flag is ignored. + * + * Node link array index constants: (Each node has an array of three + * pointers. One to the left, one to the right, and one back to the + * parent.) + * LEFT - Left child pointer. + * PARENT - Parent pointer. + * RIGHT - Right child pointer. + * EQUAL - Synonym for PARENT. + * + * ubi_trCompOps: These values are used in the ubi_trLocate() function. + * ubi_trLT - request the first instance of the greatest key less than + * the search key. + * ubi_trLE - request the first instance of the greatest key that is less + * than or equal to the search key. + * ubi_trEQ - request the first instance of key that is equal to the + * search key. + * ubi_trGE - request the first instance of a key that is greater than + * or equal to the search key. + * ubi_trGT - request the first instance of the first key that is greater + * than the search key. + * -------------------------------------------------------------------------- ** + */ + +#define ubi_trTRUE 0xFF +#define ubi_trFALSE 0x00 + +#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ +#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ + +/* Pointer array index constants... */ +#define LEFT 0x00 +#define PARENT 0x01 +#define RIGHT 0x02 +#define EQUAL PARENT + +typedef enum { + ubi_trLT = 1, + ubi_trLE, + ubi_trEQ, + ubi_trGE, + ubi_trGT + } ubi_trCompOps; + +/* -------------------------------------------------------------------------- ** + * These three macros allow simple manipulation of pointer index values (LEFT, + * RIGHT, and PARENT). + * + * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C + * uses {negative, zero, positive} values to indicate + * {less than, equal to, greater than}. + * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, + * RIGHT} (opposite of Normalize()). Note: C comparison + * functions, such as strcmp(), return {negative, zero, + * positive} values, which are not necessarily {-1, 0, + * 1}. This macro uses the the ubi_btSgn() function to + * compensate. + * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) + * is left as is. + * -------------------------------------------------------------------------- ** + */ +#define Normalize(W) ((char)((W)-EQUAL)) +#define AbNormal(W) ((char)( EQUAL+((char)ubi_btSgn( (W) )) )) +#define RevWay(W) ((char)((W)==LEFT?RIGHT:((W)==RIGHT?LEFT:EQUAL))) + +/* -------------------------------------------------------------------------- ** + * These macros allow us to quickly read the values of the OVERWRITE and + * DUPlicate KEY bits of the tree root flags field. + * -------------------------------------------------------------------------- ** + */ +#define Dups_OK(A) ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) +#define Ovwt_OK(A) ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) + +/* -------------------------------------------------------------------------- ** + * Typedefs... + * + * ubi_trBool - Your typcial true or false... + * + * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to + * indicate a key that is being searched for within the tree. + * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), + * or ubi_trInsert() functions are called. + * -------------------------------------------------------------------------- ** + */ + +typedef unsigned char ubi_trBool; + +typedef void *ubi_btItemPtr; /* A pointer to data within a node. */ + +/* ------------------------------------------------------------------------- ** + * Binary Tree Node Structure: This structure defines the basic elements of + * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! + * But, of course, I have to put the structure into this header so that + * you can use it as a building block. + * + * The fields are as follows: + * Link - an array of pointers. These pointers are manipulated by + * the BT routines. The pointers indicate the left and right + * child nodes and the parent node. By keeping track of the + * parent pointer, we avoid the need for recursive routines or + * hand-tooled stacks to keep track of our path back to the + * root. The use of these pointers is subject to change without + * notice. + * gender - a one-byte field indicating whether the node is the RIGHT or + * LEFT child of its parent. If the node is the root of the + * tree, gender will be PARENT. + * ------------------------------------------------------------------------- ** + */ +typedef struct ubi_btNodeStruct { + struct ubi_btNodeStruct *Link[ 3 ]; + char gender; + } ubi_btNode; + +typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ + +/* ------------------------------------------------------------------------- ** + * The next three typedefs define standard function types used by the binary + * tree management routines. In particular: + * + * ubi_btCompFunc is a pointer to a comparison function. Comparison + * functions are passed an ubi_btItemPtr and an + * ubi_btNodePtr. They return a value that is (<0), 0, + * or (>0) to indicate that the Item is (respectively) + * "less than", "equal to", or "greater than" the Item + * contained within the node. (See ubi_btInitTree()). + * ubi_btActionRtn is a pointer to a function that may be called for each + * node visited when performing a tree traversal (see + * ubi_btTraverse()). The function will be passed two + * parameters: the first is a pointer to a node in the + * tree, the second is a generic pointer that may point to + * anything that you like. + * ubi_btKillNodeRtn is a pointer to a function that will deallocate the + * memory used by a node (see ubi_btKillTree()). Since + * memory management is left up to you, deallocation may + * mean anything that you want it to mean. Just remember + * that the tree *will* be destroyed and that none of the + * node pointers will be valid any more. + * ------------------------------------------------------------------------- ** + */ + +typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); + +typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); + +typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); + +/* -------------------------------------------------------------------------- ** + * Tree Root Structure: This structure gives us a convenient handle for + * accessing whole AVL trees. The fields are: + * root - A pointer to the root node of the AVL tree. + * count - A count of the number of nodes stored in the tree. + * cmp - A pointer to the comparison routine to be used when building or + * searching the tree. + * flags - A set of bit flags. Two flags are currently defined: + * + * ubi_trOVERWRITE - If set, this flag indicates that a new node should + * (bit 0x01) overwrite an old node if the two have identical + * keys (ie., the keys are equal). + * ubi_trDUPKEY - If set, this flag indicates that the tree is + * (bit 0x02) allowed to contain nodes with duplicate keys. + * + * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. + * + * All of these values are set when you initialize the root structure by + * calling ubi_trInitTree(). + * -------------------------------------------------------------------------- ** + */ + +typedef struct { + ubi_btNodePtr root; /* A pointer to the root node of the tree */ + unsigned long count; /* A count of the number of nodes in the tree */ + ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ + unsigned char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ + } ubi_btRoot; + +typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ + + +/* -------------------------------------------------------------------------- ** + * Function Prototypes. + */ + +long ubi_btSgn( long x ); + /* ------------------------------------------------------------------------ ** + * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. + * + * Input: x - a signed long integer value. + * + * Output: the "sign" of x, represented as follows: + * -1 == negative + * 0 == zero (no sign) + * 1 == positive + * + * Note: This utility is provided in order to facilitate the conversion + * of C comparison function return values into BinTree direction + * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the + * AbNormal() conversion macro! + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a tree node. + * + * Input: a pointer to a ubi_btNode structure to be initialized. + * Output: a pointer to the initialized ubi_btNode structure (ie. the + * same as the input pointer). + * ------------------------------------------------------------------------ ** + */ + +ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, + ubi_btCompFunc CompFunc, + unsigned char Flags ); + /* ------------------------------------------------------------------------ ** + * Initialize the fields of a Tree Root header structure. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure to be + * initialized. + * CompFunc - a pointer to a comparison function that will be used + * whenever nodes in the tree must be compared against + * outside values. + * Flags - One bytes worth of flags. Flags include + * ubi_trOVERWRITE and ubi_trDUPKEY. See the header + * file for more info. + * + * Output: a pointer to the initialized ubi_btRoot structure (ie. the + * same value as RootPtr). + * + * Note: The interface to this function has changed from that of + * previous versions. The <Flags> parameter replaces two + * boolean parameters that had the same basic effect. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, + ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_btLocate(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Next node in the + * tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "next" node in the tree, or NULL if P pointed + * to the "last" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Previous node in + * the tree. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "previous" node in the tree, or NULL if P + * pointed to the "first" node in the tree or was NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) First node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "first" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); + /* ------------------------------------------------------------------------ ** + * Given the node indicated by P, find the (sorted order) Last node in the + * subtree of which *P is the root. + * Input: P - a pointer to a node that exists in a binary tree. + * Output: A pointer to the "last" node in a subtree that has *P as its + * root. This function will return NULL only if P is NULL. + * Note: In general, you will be passing in the value of the root field + * of an ubi_btRoot structure. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the first (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the first node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, + ubi_btItemPtr MatchMe, + ubi_btNodePtr p ); + /* ------------------------------------------------------------------------ ** + * Given a tree that a allows duplicate keys, and a pointer to a node in + * the tree, this function will return a pointer to the last (traversal + * order) node with the same key value. + * + * Input: RootPtr - A pointer to the root of the tree. + * MatchMe - A pointer to the key value. This should probably + * point to the key within node *p. + * p - A pointer to a node in the tree. + * Output: A pointer to the last node in the set of nodes with keys + * matching <FindMe>. + * Notes: Node *p MUST be in the set of nodes with keys matching + * <FindMe>. If not, this function will return NULL. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, + ubi_btActionRtn EachNode, + void *UserData ); + /* ------------------------------------------------------------------------ ** + * Traverse a tree in sorted order (non-recursively). At each node, call + * (*EachNode)(), passing a pointer to the current node, and UserData as the + * second parameter. + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the tree to be traversed. + * EachNode - a pointer to a function to be called at each node + * as the node is visited. + * UserData - a generic pointer that may point to anything that + * you choose. + * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. + * ------------------------------------------------------------------------ ** + */ + +ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, + ubi_btKillNodeRtn FreeNode ); + /* ------------------------------------------------------------------------ ** + * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot + * structure. Note that this function will return FALSE if either parameter + * is NULL. + * + * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates + * the root of the tree to delete. + * FreeNode - a function that will be called for each node in the + * tree to deallocate the memory used by the node. + * + * Output: A boolean value. FALSE if either input parameter was NULL, else + * TRUE. + * + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); + /* ------------------------------------------------------------------------ ** + * Returns a pointer to a leaf node. + * + * Input: leader - Pointer to a node at which to start the descent. + * + * Output: A pointer to a leaf node selected in a somewhat arbitrary + * manner. + * + * Notes: I wrote this function because I was using splay trees as a + * database cache. The cache had a maximum size on it, and I + * needed a way of choosing a node to sacrifice if the cache + * became full. In a splay tree, less recently accessed nodes + * tend toward the bottom of the tree, meaning that leaf nodes + * are good candidates for removal. (I really can't think of + * any other reason to use this function.) + * + In a simple binary tree or an AVL tree, the most recently + * added nodes tend to be nearer the bottom, making this a *bad* + * way to choose which node to remove from the cache. + * + Randomizing the traversal order is probably a good idea. You + * can improve the randomization of leaf node selection by passing + * in pointers to nodes other than the root node each time. A + * pointer to any node in the tree will do. Of course, if you + * pass a pointer to a leaf node you'll get the same thing back. + * + * ------------------------------------------------------------------------ ** + */ + + +int ubi_btModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#define ubi_trItemPtr ubi_btItemPtr + +#define ubi_trNode ubi_btNode +#define ubi_trNodePtr ubi_btNodePtr + +#define ubi_trRoot ubi_btRoot +#define ubi_trRootPtr ubi_btRootPtr + +#define ubi_trCompFunc ubi_btCompFunc +#define ubi_trActionRtn ubi_btActionRtn +#define ubi_trKillNodeRtn ubi_btKillNodeRtn + +#define ubi_trSgn( x ) ubi_btSgn( x ) + +#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) + +#define ubi_trInitTree( Rp, Cf, Fl ) \ + ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_btLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) + +#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) + +#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) + +#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) + +#define ubi_trFirstOf( Rp, Ip, P ) \ + ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trLastOf( Rp, Ip, P ) \ + ubi_btLastOf( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_btNodePtr)(P) ) + +#define ubi_trTraverse( Rp, En, Ud ) \ + ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) + +#define ubi_trKillTree( Rp, Fn ) \ + ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) + +#define ubi_trLeafNode( Nd ) \ + ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) + +#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) + +/* ========================================================================== */ +#endif /* ubi_BinTree_H */ diff --git a/source/ubiqx/ubi_SplayTree.c b/source/ubiqx/ubi_SplayTree.c new file mode 100644 index 00000000000..e6b30dd8fcc --- /dev/null +++ b/source/ubiqx/ubi_SplayTree.c @@ -0,0 +1,468 @@ +/* ========================================================================== ** + * ubi_SplayTree.c + * + * Copyright (C) 1993-1995 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.c,v $ + * Revision 1.1 1997/10/10 14:46:40 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.5 1997/07/26 04:15:42 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 04:42:21 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:07 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:54:42 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:46 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * Revision 1.1 93/10/18 20:35:16 CRH + * I removed the hard-coded logical device names from the include file + * specifications. CRH + * + * Revision 1.0 93/10/15 23:00:15 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.1 93/04/25 22:03:32 CRH + * Simply changed the <exec/types.h> #include reference the .c file to + * use <stdlib.h> instead. The latter is portable, the former is not. + * + * Revision 0.0 93/04/21 23:05:52 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include <stdlib.h> /* Defines NULL for us. */ +#include "ubi_SplayTree.h" /* Header for THIS module. */ + +/* ========================================================================== ** + * Static data. + */ + +static char ModuleID[] = "ubi_SplayTree\n\ +\t$Revision: 1.1 $\n\ +\t$Date: 1997/10/10 14:46:40 $\n\ +\t$Author: crh $\n"; + + +/* ========================================================================== ** + * Private functions... + */ + +static void Rotate( ubi_btNodePtr p ) + /* ------------------------------------------------------------------------ ** + * This function performs a single rotation, moving node *p up one level + * in the tree. + * + * Input: p - a pointer to an ubi_btNode in a tree. + * + * Output: None. + * + * Notes: This implements a single rotation in either direction (left + * or right). This is the basic building block of all splay + * tree rotations. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parentp; + ubi_btNodePtr tmp; + char way; + char revway; + + parentp = p->Link[PARENT]; /* Find parent. */ + + if( parentp ) /* If no parent, then we're already the root. */ + { + way = p->gender; + revway = RevWay(way); + tmp = p->Link[revway]; + + parentp->Link[way] = tmp; + if( tmp ) + { + tmp->Link[PARENT] = parentp; + tmp->gender = way; + } + + tmp = parentp->Link[PARENT]; + p->Link[PARENT] = tmp; + p->gender = parentp->gender; + if( tmp ) + tmp->Link[p->gender] = p; + + parentp->Link[PARENT] = p; + parentp->gender = revway; + p->Link[revway] = parentp; + } + } /* Rotate */ + +static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) + /* ------------------------------------------------------------------------ ** + * Move the node indicated by SplayWithMe to the root of the tree by + * splaying the tree. + * + * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. + * + * Output: A pointer to the root of the splay tree (i.e., the same as + * SplayWithMe). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr parent; + + while( (parent = SplayWithMe->Link[PARENT]) ) + { + if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ + Rotate( parent ); + else + { + if( EQUAL != parent->gender ) /* Zig-Zag */ + Rotate( SplayWithMe ); + } + Rotate( SplayWithMe ); /* Zig */ + } /* while */ + return( SplayWithMe ); + } /* Splay */ + +/* ========================================================================== ** + * Exported utilities. + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ) + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr OtherP; + + if( !(OldNode) ) + OldNode = &OtherP; + + if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) + { + RootPtr->root = Splay( NewNode ); + return( ubi_trTRUE ); + } + + /* Splay the unreplacable, duplicate keyed, unique, old node. */ + RootPtr->root = Splay( (*OldNode) ); + return( ubi_trFALSE ); + } /* ubi_sptInsert */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + (void)Splay( DeadNode ); /* Move dead node to root. */ + if( (p = DeadNode->Link[LEFT]) ) /* If left subtree exists... */ + { + ubi_btNodePtr q = DeadNode->Link[RIGHT]; + + p->Link[PARENT] = NULL; /* Left subtree node becomes root.*/ + p->gender = PARENT; + p = ubi_btLast( p ); /* Find rightmost left tree node..*/ + p->Link[RIGHT] = q; /* ...attach right tree. */ + if( q ) + q->Link[PARENT] = p; + RootPtr->root = Splay( p ); /* Resplay at p. */ + } + else + { + if( (p = DeadNode->Link[RIGHT]) ) /* No left, but right subtree... */ + { /* ...exists... */ + p->Link[PARENT] = NULL; /* Right subtree root becomes... */ + p->gender = PARENT; /* ...overall tree root. */ + RootPtr->root = p; + } + else + RootPtr->root = NULL; /* No subtrees => empty tree. */ + } + + (RootPtr->count)--; /* Decrement node count. */ + return( DeadNode ); /* Return pointer to pruned node. */ + } /* ubi_sptRemove */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ) + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btLocate( RootPtr, FindMe, CompOp ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptLocate */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ) + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + { + ubi_btNodePtr p; + + p = ubi_btFind( RootPtr, FindMe ); + if( p ) + RootPtr->root = Splay( p ); + return( p ); + } /* ubi_sptFind */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ) + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + { + RootPtr->root = Splay( SplayMe ); + } /* ubi_sptSplay */ + +int ubi_sptModuleID( int size, char *list[] ) + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + { + if( size > 0 ) + { + list[0] = ModuleID; + if( size > 1 ) + return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); + return( 1 ); + } + return( 0 ); + } /* ubi_sptModuleID */ + +/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_SplayTree.h b/source/ubiqx/ubi_SplayTree.h new file mode 100644 index 00000000000..d20933ed4ce --- /dev/null +++ b/source/ubiqx/ubi_SplayTree.h @@ -0,0 +1,335 @@ +#ifndef ubi_SplayTree_H +#define ubi_SplayTree_H +/* ========================================================================== ** + * ubi_SplayTree.h + * + * Copyright (C) 1993,1995 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * + * This module implements "splay" trees. Splay trees are binary trees + * that are rearranged (splayed) whenever a node is accessed. The + * splaying process *tends* to make the tree bushier (improves balance), + * and the nodes that are accessed most frequently *tend* to be closer to + * the top. + * + * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and + * Robert Tarjan. Journal of the Association for Computing + * Machinery Vol 32, No. 3, July 1985 pp. 652-686 + * + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_SplayTree.h,v $ + * Revision 1.1 1997/10/10 14:46:42 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 2.5 1997/07/26 04:15:46 crh + * + Cleaned up a few minor syntax annoyances that gcc discovered for me. + * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. + * + * Revision 2.4 1997/06/03 05:22:56 crh + * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing + * problems. + * + * Revision 2.3 1995/10/03 22:19:37 CRH + * Ubisized! + * Also, added the function ubi_sptSplay(). + * + * Revision 2.1 95/03/09 23:55:04 CRH + * Added the ModuleID static string and function. These modules are now + * self-identifying. + * + * Revision 2.0 95/02/27 22:34:55 CRH + * This module was updated to match the interface changes made to the + * ubi_BinTree module. In particular, the interface to the Locate() function + * has changed. See ubi_BinTree for more information on changes and new + * functions. + * + * The revision number was also upped to match ubi_BinTree. + * + * + * Revision 1.0 93/10/15 22:59:36 CRH + * With this revision, I have added a set of #define's that provide a single, + * standard API to all existing tree modules. Until now, each of the three + * existing modules had a different function and typedef prefix, as follows: + * + * Module Prefix + * ubi_BinTree ubi_bt + * ubi_AVLtree ubi_avl + * ubi_SplayTree ubi_spt + * + * To further complicate matters, only those portions of the base module + * (ubi_BinTree) that were superceeded in the new module had the new names. + * For example, if you were using ubi_AVLtree, the AVL node structure was + * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using + * SplayTree, the locate function was called "ubi_sptLocate", but the next + * and previous functions remained "ubi_btNext" and "ubi_btPrev". + * + * This was not too terrible if you were familiar with the modules and knew + * exactly which tree model you wanted to use. If you wanted to be able to + * change modules (for speed comparisons, etc), things could get messy very + * quickly. + * + * So, I have added a set of defined names that get redefined in any of the + * descendant modules. To use this standardized interface in your code, + * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with + * "ubi_tr". The "ubi_tr" names will resolve to the correct function or + * datatype names for the module that you are using. Just remember to + * include the header for that module in your program file. Because these + * names are handled by the preprocessor, there is no added run-time + * overhead. + * + * Note that the original names do still exist, and can be used if you wish + * to write code directly to a specific module. This should probably only be + * done if you are planning to implement a new descendant type, such as + * red/black trees. CRH + * + * Revision 0.0 93/04/21 23:07:13 CRH + * Initial version, written by Christopher R. Hertel. + * This module implements Splay Trees using the ubi_BinTree module as a basis. + * + * ========================================================================== ** + */ + +#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, + ubi_btNodePtr NewNode, + ubi_btItemPtr ItemPtr, + ubi_btNodePtr *OldNode ); + /* ------------------------------------------------------------------------ ** + * This function uses a non-recursive algorithm to add a new element to the + * splay tree. + * + * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates + * the root of the tree to which NewNode is to be added. + * NewNode - a pointer to an ubi_btNode structure that is NOT + * part of any tree. + * ItemPtr - A pointer to the sort key that is stored within + * *NewNode. ItemPtr MUST point to information stored + * in *NewNode or an EXACT DUPLICATE. The key data + * indicated by ItemPtr is used to place the new node + * into the tree. + * OldNode - a pointer to an ubi_btNodePtr. When searching + * the tree, a duplicate node may be found. If + * duplicates are allowed, then the new node will + * be simply placed into the tree. If duplicates + * are not allowed, however, then one of two things + * may happen. + * 1) if overwritting *is not* allowed, this + * function will return FALSE (indicating that + * the new node could not be inserted), and + * *OldNode will point to the duplicate that is + * still in the tree. + * 2) if overwritting *is* allowed, then this + * function will swap **OldNode for *NewNode. + * In this case, *OldNode will point to the node + * that was removed (thus allowing you to free + * the node). + * ** If you are using overwrite mode, ALWAYS ** + * ** check the return value of this parameter! ** + * Note: You may pass NULL in this parameter, the + * function knows how to cope. If you do this, + * however, there will be no way to return a + * pointer to an old (ie. replaced) node (which is + * a problem if you are using overwrite mode). + * + * Output: a boolean value indicating success or failure. The function + * will return FALSE if the node could not be added to the tree. + * Such failure will only occur if duplicates are not allowed, + * nodes cannot be overwritten, AND a duplicate key was found + * within the tree. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); + /* ------------------------------------------------------------------------ ** + * This function removes the indicated node from the tree. + * + * Input: RootPtr - A pointer to the header of the tree that contains + * the node to be removed. + * DeadNode - A pointer to the node that will be removed. + * + * Output: This function returns a pointer to the node that was removed + * from the tree (ie. the same as DeadNode). + * + * Note: The node MUST be in the tree indicated by RootPtr. If not, + * strange and evil things will happen to your trees. + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe, + ubi_trCompOps CompOp ); + /* ------------------------------------------------------------------------ ** + * The purpose of ubi_btLocate() is to find a node or set of nodes given + * a target value and a "comparison operator". The Locate() function is + * more flexible and (in the case of trees that may contain dupicate keys) + * more precise than the ubi_btFind() function. The latter is faster, + * but it only searches for exact matches and, if the tree contains + * duplicates, Find() may return a pointer to any one of the duplicate- + * keyed records. + * + * Input: + * RootPtr - A pointer to the header of the tree to be searched. + * FindMe - An ubi_btItemPtr that indicates the key for which to + * search. + * CompOp - One of the following: + * CompOp Return a pointer to the node with + * ------ --------------------------------- + * ubi_trLT - the last key value that is less + * than FindMe. + * ubi_trLE - the first key matching FindMe, or + * the last key that is less than + * FindMe. + * ubi_trEQ - the first key matching FindMe. + * ubi_trGE - the first key matching FindMe, or the + * first key greater than FindMe. + * ubi_trGT - the first key greater than FindMe. + * Output: + * A pointer to the node matching the criteria listed above under + * CompOp, or NULL if no node matched the criteria. + * + * Notes: + * In the case of trees with duplicate keys, Locate() will behave as + * follows: + * + * Find: 3 Find: 3 + * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 + * ^ ^ ^ ^ ^ + * LT EQ GT LE GE + * + * That is, when returning a pointer to a node with a key that is LESS + * THAN the target key (FindMe), Locate() will return a pointer to the + * LAST matching node. + * When returning a pointer to a node with a key that is GREATER + * THAN the target key (FindMe), Locate() will return a pointer to the + * FIRST matching node. + * + * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). + * ------------------------------------------------------------------------ ** + */ + +ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, + ubi_btItemPtr FindMe ); + /* ------------------------------------------------------------------------ ** + * This function performs a non-recursive search of a tree for any node + * matching a specific key. + * + * Input: + * RootPtr - a pointer to the header of the tree to be searched. + * FindMe - a pointer to the key value for which to search. + * + * Output: + * A pointer to a node with a key that matches the key indicated by + * FindMe, or NULL if no such node was found. + * + * Note: In a tree that allows duplicates, the pointer returned *might + * not* point to the (sequentially) first occurance of the + * desired key. In such a tree, it may be more useful to use + * ubi_sptLocate(). + * ------------------------------------------------------------------------ ** + */ + +void ubi_sptSplay( ubi_btRootPtr RootPtr, + ubi_btNodePtr SplayMe ); + /* ------------------------------------------------------------------------ ** + * This function allows you to splay the tree at a given node, thus moving + * the node to the top of the tree. + * + * Input: + * RootPtr - a pointer to the header of the tree to be splayed. + * SplayMe - a pointer to a node within the tree. This will become + * the new root node. + * Output: None. + * + * Notes: This is an uncharacteristic function for this group of modules + * in that it provides access to the internal balancing routines, + * which would normally be hidden. + * Splaying the tree will not damage it (assuming that I've done + * *my* job), but there is overhead involved. I don't recommend + * that you use this function unless you understand the underlying + * Splay Tree principles involved. + * ------------------------------------------------------------------------ ** + */ + +int ubi_sptModuleID( int size, char *list[] ); + /* ------------------------------------------------------------------------ ** + * Returns a set of strings that identify the module. + * + * Input: size - The number of elements in the array <list>. + * list - An array of pointers of type (char *). This array + * should, initially, be empty. This function will fill + * in the array with pointers to strings. + * Output: The number of elements of <list> that were used. If this value + * is less than <size>, the values of the remaining elements are + * not guaranteed. + * + * Notes: Please keep in mind that the pointers returned indicate strings + * stored in static memory. Don't free() them, don't write over + * them, etc. Just read them. + * ------------------------------------------------------------------------ ** + */ + +/* -------------------------------------------------------------------------- ** + * Masquarade... + * + * This set of defines allows you to write programs that will use any of the + * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). + * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by + * including the appropriate module header. + */ + +#undef ubi_trInsert +#undef ubi_trRemove +#undef ubi_trLocate +#undef ubi_trFind +#undef ubi_trModuleID + +#define ubi_trInsert( Rp, Nn, Ip, On ) \ + ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ + (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) + +#define ubi_trRemove( Rp, Dn ) \ + ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) + +#define ubi_trLocate( Rp, Ip, Op ) \ + ubi_sptLocate( (ubi_btRootPtr)(Rp), \ + (ubi_btItemPtr)(Ip), \ + (ubi_trCompOps)(Op) ) + +#define ubi_trFind( Rp, Ip ) \ + ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) + +#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) + +/* ================================ The End ================================= */ +#endif /* ubi_SplayTree_H */ + + + + + diff --git a/source/ubiqx/ubi_dLinkList.c b/source/ubiqx/ubi_dLinkList.c new file mode 100644 index 00000000000..0bec3323edc --- /dev/null +++ b/source/ubiqx/ubi_dLinkList.c @@ -0,0 +1,144 @@ +/* ========================================================================== ** + * ubi_dLinkList.c + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_dLinkList.c,v $ + * Revision 1.1 1997/10/10 14:46:43 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 0.1 1997/10/07 04:34:07 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include "ubi_dLinkList.h" + +/* ========================================================================== ** + * Functions... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->Tail = NULL; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_dlInitList */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ) + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL == After ) + { + New->Next = ListPtr->Head; + New->Prev = NULL; + if( NULL != ListPtr->Head ) + ListPtr->Head->Prev = New; + else + ListPtr->Tail = New; + ListPtr->Head = New; + } + else + { + New->Next = After->Next; + New->Prev = After; + if( NULL != After->Next ) + After->Next->Prev = New; + else + ListPtr->Tail = New; + After->Next = New; + } + + ++(ListPtr->count); + + return( New ); + } /* ubi_dlInsert */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL != Old ) + { + if( Old->Next ) + Old->Next->Prev = Old->Prev; + else + ListPtr->Tail = Old->Prev; + + if( Old->Prev ) + Old->Prev->Next = Old->Next; + else + ListPtr->Head = Old->Next; + + --(ListPtr->count); + } + + return( Old ); + } /* ubi_dlRemove */ + + +/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_dLinkList.h b/source/ubiqx/ubi_dLinkList.h new file mode 100644 index 00000000000..5204f35eaf7 --- /dev/null +++ b/source/ubiqx/ubi_dLinkList.h @@ -0,0 +1,155 @@ +#ifndef ubi_dLinkList_H +#define ubi_dLinkList_H +/* ========================================================================== ** + * ubi_dLinkList.h + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_dLinkList.h,v $ + * Revision 1.1 1997/10/10 14:46:43 crh + * This is the ubiqx binary tree and linked list library. + * This library is being included as part of the Samba distribution. + * (Hurray!) + * + * Revision 0.1 1997/10/07 04:34:38 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include <stdlib.h> + + +/* ========================================================================== ** + * Typedefs... + * + * ubi_dlNode - This is the basic node structure. + * ubi_dlNodePtr - Pointer to a node. + * ubi_dlList - This is the list header structure. + * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_dlListNode + { + struct ubi_dlListNode *Next; + struct ubi_dlListNode *Prev; + } ubi_dlNode; + +typedef ubi_dlNode *ubi_dlNodePtr; + +typedef struct + { + ubi_dlNodePtr Head; + ubi_dlNodePtr Tail; + unsigned long count; + } ubi_dlList; + +typedef ubi_dlList *ubi_dlListPtr; + +/* ========================================================================== ** + * Macros... + * + * ubi_dlAddHead - Add a new node at the head of the list. + * ubi_dlAddTail - Add a new node at the tail of the list. + * ubi_dlRemHead - Remove the node at the head of the list, if any. + * ubi_dlRemTail - Remove the node at the tail of the list, if any. + * ubi_dlFirst - Return a pointer to the first node in the list, if any. + * ubi_dlLast - Return a pointer to the last node in the list, if any. + * ubi_dlNext - Given a node, return a pointer to the next node. + * ubi_dlPrev - Given a node, return a pointer to the previous node. + */ + +#define ubi_dlAddHead( L, N ) ubi_dlInsert( (L), (N), NULL ) + +#define ubi_dlAddTail( L, N ) ubi_dlInsert( (L), (N), ((L)->Tail) ) + +#define ubi_dlRemHead( L ) ubi_dlRemove( (L), ((L)->Head) ) + +#define ubi_dlRemTail( L ) ubi_dlRemove( (L), ((L)->Tail) ) + +#define ubi_dlFirst( L ) ((L)->Head) + +#define ubi_dlLast( L ) ((L)->Tail) + +#define ubi_dlNext( N ) ((N)->Next) + +#define ubi_dlPrev( N ) ((N)->Prev) + + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ); + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + + +/* ================================ The End ================================= */ +#endif /* ubi_dLinkList_H */ -- cgit From 87a0a944855a673d693d934e446bdc231b1c7f02 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 14:48:05 +0000 Subject: Makefile: added credentials.c to smbd credentials.c: using credential structures instead of char* password.c uid.c server.c: added sid and attr to user_struct. smbdes.c: smbhash and str_to_key make public instead of private. pipes.c smb.h: lsa structures, sub-functions. proto.h: usual. --- source/include/proto.h | 17 +- source/include/smb.h | 43 +- source/libsmb/credentials.c | 30 +- source/libsmb/smbdes.c | 4 +- source/smbd/password.c | 97 ++-- source/smbd/pipes.c | 1063 ++++++++++++++++++++++++++++++++++++++++++- source/smbd/server.c | 22 +- source/smbd/uid.c | 15 +- 8 files changed, 1195 insertions(+), 96 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 009d83db5c2..94937daade4 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -60,6 +60,15 @@ int process_tar(char *inbuf, char *outbuf); int clipfind(char **aret, int ret, char *tok); int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind); +/*The following definitions come from credentials.c */ + +void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, + char *session_key); +void cred_create(char *session_key, DOM_CHAL *stored_cred, UTIME timestamp, + DOM_CHAL *cred); +int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, + UTIME timestamp); + /*The following definitions come from dir.c */ void init_dptrs(void); @@ -629,10 +638,11 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len); char *dom_sid_to_string(DOM_SID *sid); -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, +BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); +void no_fn(uint uid); /*The following definitions come from predict.c */ @@ -755,7 +765,8 @@ BOOL request_oplock_break(min_share_mode_entry *share_entry, BOOL snum_used(int snum); BOOL reload_services(BOOL test); int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups); + int **p_igroups, gid_t **p_groups, + int **p_attrs); int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid); int find_free_file(void ); int reply_corep(char *outbuf); @@ -791,6 +802,8 @@ BOOL smb_shm_get_usage(int *bytes_free, /*The following definitions come from smbdes.c */ +void str_to_key(unsigned char *str,unsigned char *key); +void smbhash(unsigned char *out, unsigned char *in, unsigned char *key); void E_P16(unsigned char *p14,unsigned char *p16); void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); diff --git a/source/include/smb.h b/source/include/smb.h index 54ce9e88e88..87fcb22cac9 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -877,7 +877,8 @@ Response: */ -struct smb_passwd { +struct smb_passwd +{ int smb_userid; char *smb_name; unsigned char *smb_passwd; /* Null if no password */ @@ -886,12 +887,14 @@ struct smb_passwd { }; -struct current_user { +struct current_user +{ int cnum, id; int uid, gid; int ngroups; gid_t *groups; int *igroups; + int *attrs; }; typedef struct @@ -988,35 +991,63 @@ typedef struct char *user; /* name of user who *opened* this connection */ int uid; /* uid of user who *opened* this connection */ int gid; /* gid of user who *opened* this connection */ + uint16 vuid; /* vuid of user who *opened* this connection, or UID_FIELD_INVALID */ + /* following groups stuff added by ih */ + /* This groups info is valid for the user that *opened* the connection */ int ngroups; gid_t *groups; int *igroups; /* an integer version - some OSes are broken :-( */ + int *attrs; + time_t lastused; BOOL used; int num_files_open; name_compare_entry *hide_list; /* Per-share list of files to return as hidden. */ name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */ + } connection_struct; +/* Domain controller authentication protocol info */ +struct dcinfo +{ + DOM_CHAL clnt_chal; /* Initial challenge received from client */ + DOM_CHAL srv_chal; /* Initial server challenge */ + DOM_CHAL clnt_cred; /* Last client credential */ + DOM_CHAL srv_cred; /* Last server credential */ + + char sess_key[8]; /* Session key */ + uchar md4pw[16]; /* md4(machine password) */ +}; typedef struct { int uid; /* uid of a validated user */ int gid; /* gid of a validated user */ + fstring name; /* name of a validated user */ + fstring real_name; /* to store real name from password file - simeon */ BOOL guest; + /* following groups stuff added by ih */ /* This groups info is needed for when we become_user() for this uid */ - int user_ngroups; - gid_t *user_groups; - int *user_igroups; /* an integer version - some OSes are broken :-( */ + int n_groups; + gid_t *groups; + int *igroups; /* an integer version - some OSes are broken :-( */ + int *attrs; /* attributes associated with each gid */ + #if (defined(NETGROUP) && defined(AUTOMOUNT)) char *home_share; /* to store NIS home of a user - simeon */ #endif - char *real_name; /* to store real name from password file - simeon */ + + int n_sids; + int *sids; + + /* per-user authentication information on NT RPCs */ + struct dcinfo dc; + } user_struct; diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index 4c81177fb20..eb1039ddb0b 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -30,21 +30,21 @@ Input: 8 byte challenge block Output: 8 byte session key ****************************************************************************/ -void cred_session_key(char *challenge, char *srv_challenge, char *pass, +void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, char *session_key) { uint32 sum[2]; char sum2[8]; char buf[8]; - sum[0] = IVAL(challenge, 0) + IVAL(srv_challenge, 0); - sum[1] = IVAL(challenge, 4) + IVAL(srv_challenge, 4); + sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); + sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - E1(pass,sum2,buf); - E1(pass+9,buf,session_key); + smbhash(pass, sum2, buf); + smbhash(pass+9,buf,session_key); } @@ -59,20 +59,20 @@ Input: Output: 8 byte credential ****************************************************************************/ -void cred_create(char *session_key, char *stored_cred, UTIME timestamp, - char *cred) +void cred_create(char *session_key, DOM_CHAL *stored_cred, UTIME timestamp, + DOM_CHAL *cred) { char key2[7]; char buf[8]; char timecred[8]; - memcpy(timecred, stored_cred, 8); + memcpy(timecred, stored_cred->data, 8); SIVAL(timecred, 0, IVAL(stored_cred, 0) + timestamp.time); - E1(session_key, timecred, buf); + smbhash(session_key, timecred, buf); memset(key2, 0, 7); key2[0] = session_key[7]; - E1(key2, buf, cred); + smbhash(key2, buf, cred->data); } @@ -89,13 +89,13 @@ Output: returns 1 if computed credential matches received credential returns 0 otherwise ****************************************************************************/ -int cred_assert(char *cred, char *session_key, char *stored_cred, - NTTIME timestamp) +int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, + UTIME timestamp) { - char cred2[8]; + DOM_CHAL cred2; - cred_create(session_key, stored_cred, timestamp, cred2); + cred_create(session_key, stored_cred, timestamp, &cred2); - return memcmp(cred, cred2, 8) == 0; + return memcmp(cred->data, cred2.data, 8) == 0; } diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c index 1c38612b739..b62a160418d 100644 --- a/source/libsmb/smbdes.c +++ b/source/libsmb/smbdes.c @@ -257,7 +257,7 @@ static void dohash(char *out, char *in, char *key) permute(out, rl, perm6, 64); } -static void str_to_key(unsigned char *str,unsigned char *key) +void str_to_key(unsigned char *str,unsigned char *key) { int i; @@ -275,7 +275,7 @@ static void str_to_key(unsigned char *str,unsigned char *key) } -static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) +void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) { int i; char outb[64]; diff --git a/source/smbd/password.c b/source/smbd/password.c index f4d94791cf3..af9be289c7d 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -96,10 +96,10 @@ tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ user_struct *get_valid_user_struct(uint16 vuid) { - if(vuid == UID_FIELD_INVALID) + if (vuid == UID_FIELD_INVALID) return NULL; vuid -= VUID_OFFSET; - if((vuid >= (uint16)num_validated_users) || + if ((vuid >= (uint16)num_validated_users) || (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) return NULL; return &validated_users[vuid]; @@ -111,19 +111,28 @@ invalidate a uid void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) - return; + + if (vuser == NULL) return; vuser->uid = -1; vuser->gid = -1; - vuser->user_ngroups = 0; - if(vuser->user_groups && - (vuser->user_groups != (gid_t *)vuser->user_igroups)) - free(vuser->user_groups); - vuser->user_groups = NULL; - if(vuser->user_igroups) - free(vuser->user_igroups); - vuser->user_igroups = NULL; + + vuser->n_sids = 0; + + /* same number of igroups as groups as attrs */ + vuser->n_groups = 0; + + if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups)) + free(vuser->groups); + + if (vuser->igroups) free(vuser->igroups); + if (vuser->attrs ) free(vuser->attrs); + if (vuser->sids ) free(vuser->sids); + + vuser->attrs = NULL; + vuser->sids = NULL; + vuser->igroups = NULL; + vuser->groups = NULL; } @@ -133,7 +142,7 @@ return a validated username char *validated_username(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) + if (vuser == NULL) return 0; return(vuser->name); } @@ -156,12 +165,11 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) int home_server_len; #endif struct passwd *pwfile; /* for getting real name from passwd file */ - int real_name_len; #if 0 /* * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does it's own + * I belive this code is incorrect. Each service does its own * sessionsetup_and_X for the same user, and as each service shuts * down, it does a user_logoff_and_X. As we are consolidating multiple * sessionsetup_and_X's onto the same vuid here, when the first service @@ -174,7 +182,7 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) int i; for(i = 0; i < num_validated_users; i++) { vuser = &validated_users[i]; - if( vuser->uid == uid ) + if ( vuser->uid == uid ) return (uint16)(i + VUID_OFFSET); /* User already validated */ } #endif @@ -198,16 +206,21 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->guest = guest; strcpy(vuser->name,name); - vuser->user_ngroups = 0; - vuser->user_groups = NULL; - vuser->user_igroups = NULL; + vuser->n_sids = 0; + vuser->sids = NULL; + + vuser->n_groups = 0; + vuser->groups = NULL; + vuser->igroups = NULL; + vuser->attrs = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(name,uid,gid, - &vuser->user_ngroups, - &vuser->user_igroups, - &vuser->user_groups); + &vuser->n_groups, + &vuser->igroups, + &vuser->groups, + &vuser->attrs); DEBUG(3,("uid %d registered to name %s\n",uid,name)); @@ -215,14 +228,14 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) vuser->home_share = NULL; DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); vuser->home_share = Realloc(vuser->home_share, 32); - strcpy(vuser->home_share,"\\\\%L\\HOMES"); + strcpy(vuser->home_share,"\\\\%L\\%U"); - if (nis_error = yp_get_default_domain(&nis_domain)) + if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); DEBUG(3, ("NIS Domain: %s\n", nis_domain)); - if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), - &nis_result, &nis_result_len)) + if ((nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), + &nis_result, &nis_result_len)) != 0) DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); if (!nis_error && lp_nis_home_map()) { home_server_len = strcspn(nis_result,":"); @@ -237,19 +250,13 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) } #endif - vuser->real_name = NULL; DEBUG(3, ("Clearing default real name\n")); - vuser->real_name = Realloc(vuser->real_name, 15); - strcpy(vuser->real_name, "<Full Name>\0"); + fstrcpy(vuser->real_name, "<Full Name>\0"); if (lp_unix_realname()) { - if((pwfile=getpwnam(vuser->name))!= NULL) + if ((pwfile=getpwnam(vuser->name))!= NULL) { DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - real_name_len = strcspn(pwfile->pw_gecos, ","); - DEBUG(3, ("Real name length: %d\n", real_name_len)); - vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); - strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); - vuser->real_name[real_name_len]='\0'; + fstrcpy(vuser->real_name, pwfile->pw_gecos); } } @@ -702,7 +709,7 @@ static int linux_bigcrypt(char *password,char *salt1, char *crypted) for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { char * p = crypt(password,salt) + 2; - if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) + if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) return(0); password += LINUX_PASSWORD_SEG_CHARS; crypted += strlen(p); @@ -826,10 +833,10 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha unsigned char p21[21]; unsigned char p24[24]; - if(part_passwd == NULL) + if (part_passwd == NULL) DEBUG(10,("No password set - allowing access\n")); /* No password set - always true ! */ - if(part_passwd == NULL) + if (part_passwd == NULL) return 1; memset(p21,'\0',21); @@ -905,7 +912,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); - if((pwlen == 24) && challenge_done) + if ((pwlen == 24) && challenge_done) { DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); @@ -916,28 +923,28 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) } smb_pass = get_smbpwnam(user); - if(!smb_pass) + if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } /* Ensure the uid's match */ - if(smb_pass->smb_userid != pass->pw_uid) + if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } - if(Protocol >= PROTOCOL_NT1) + if (Protocol >= PROTOCOL_NT1) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - if(smb_pass->smb_nt_passwd != NULL) + if (smb_pass->smb_nt_passwd != NULL) { DEBUG(4,("Checking NT MD4 password\n")); - if(smb_password_check(password, + if (smb_password_check(password, smb_pass->smb_nt_passwd, (unsigned char *)challenge)) { @@ -1080,7 +1087,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) } /* give up? */ - if(level < 1) + if (level < 1) { update_protected_database(user,False); diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 6937412e29f..5a6da643d98 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -492,13 +492,13 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->reserved = 0; /* reserved */ } -static void make_rpc_reply(char *inbuf, char *q, int data_len) +static int make_rpc_reply(char *inbuf, char *q, int data_len) { uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; create_rpc_reply(&hdr, callid, data_len); - smb_io_rpc_hdr(False, &hdr, q, q, 4); + return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q; } static int lsa_reply_open_policy(char *q, char *base) @@ -723,30 +723,22 @@ static int lsa_reply_lookup_rids(char *q, char *base, return q - start; } -static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) +static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, + DOM_CHAL *srv_chal, int status) { - memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); r_c->status = status; } -#if 0 - char chal[8]; - /* PAXX: set these to random values */ - for (int i = 0; i < 8; i+++) - { - chal[i] = 0xA5; - } -#endif - static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, - char chal[8]) + DOM_CHAL *srv_chal) { char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ - make_lsa_r_req_chal(&r_c, chal, 0); + make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4); @@ -1083,7 +1075,7 @@ static void api_lsa_lookup_names( char *param, char *data, *rdata_len = reply_len + 0x18; } -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, +BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) @@ -1193,4 +1185,1043 @@ BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, return True; } +static void api_lsa_req_chal( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + int i; + LSA_Q_REQ_CHAL q_r; + + fstring mach_acct; + struct smb_passwd *smb_pass; + + /* grab the challenge... */ + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + + fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr2(q_r.uni_logon_srv .buffer), + mach_acct)); + + strcat(mach_acct, "$"); + + smb_pass = get_smbpwnam(mach_acct); + if (smb_pass != NULL) + { + memcpy(vuser->dc.md4pw, smb_pass->smb_nt_passwd, sizeof(vuser->dc.md4pw)); + } + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", mach_acct)); + } + + { + char foo[16]; + for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", vuser->dc.md4pw[i]); + DEBUG(1,("pass %s %s\n", mach_acct, foo)); + } + + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), + vuser->dc.md4pw, vuser->dc.sess_key); + + /* copy the client credentials for later use */ + memcpy(vuser->dc.srv_chal.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(vuser->dc.srv_cred.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + + /* create a server challenge for the client */ + /* PAXX: set these to random values. */ + /* lkcl: paul, you mentioned that it doesn't really matter much */ + for (i = 0; i < 8; i++) + { + vuser->dc.srv_chal.data[i] = 0xA5; + } + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, + &(vuser->dc.srv_chal)); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} + +void no_fn(uint uid) +{ + user_struct *vuser = get_valid_user_struct(uid); + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif +} + +#endif /* NTDOMAIN */ + +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ + + BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + uchar rc4key[16]; + uchar ntowfpass[16]; + uint32 nentries; + char *policyhandle; + #define MAXSIDS 64 + uchar *sids[MAXSIDS]; /* for lookup SID */ + int nsids; + #define MAXNAMES 64 + uchar *names[MAXNAMES]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAOPENPOLICY: + DEBUG(1,("LSAOPENPOLICY\n")); + char *q = *rdata + 0x18; + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + /* return a 20 byte policy handle */ + /* here's a pretty handle:- */ + qSIVAL(time(NULL)); + qSIVAL(0x810a792f); + qSIVAL(0x11d107d5); + qSIVAL(time(NULL)); + qSIVAL(0x6cbcf800); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + break; + + case LSAQUERYINFOPOLICY: + DEBUG(1,("LSAQUERYINFOPOLICY\n")); + dump_data(1,data,128); + infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ + q = *rdata + 0x18; + qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose + value is ignored */ + qSSVAL(infoclass); + domainname = lp_workgroup(); + domlen = strlen(domainname); + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); + + switch (infoclass) + { + case 5: + case 3: + default: + qSSVAL(0); /* 2 undocumented bytes */ + qSSVAL(domlen*2); + qSSVAL(domlen*2); /* unicode domain len and maxlen */ + qSIVAL(4); /* domain buffer pointer */ + qSIVAL(2); /* domain sid pointer */ + qunistr(domainname); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + } + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAENUMTRUSTDOM: + DEBUG(1,("LSAENUMTRUSTDOM\n")); + q = *rdata + 0x18; + qSIVAL(0); /* enumeration context */ + qSIVAL(0); /* entries read */ + qSIVAL(0); /* trust information */ + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + break; + + case LSACLOSE: + DEBUG(1,("LSACLOSE\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAOPENSECRET: + DEBUG(1,("LSAOPENSECRET\n")); + q = *rdata + 0x18; + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + qSIVAL(0); + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + break; + + case LSALOOKUPSIDS: + DEBUG(1,("LSAOPENSECRET\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupsid entries %d\n",nentries)); + q += (2+nentries) * 4; /* skip bufptrs */ + /* now we have nentries sids of the form: + uint32 Subauthority count (SAC) + char Revision + char Subaurity count again + char[6] Identifier authority + [uint32 subauthority] * SAC + */ + for (nsids = 0; nsids < nentries; nsids++) + { + DEBUG(4,("lookupsid q in %lx\n",q)); + sids[nsids] = q; + DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); + q += 4+1+1+6+IVAL(q,0)*4; + DEBUG(4,("lookupsid q %lx\n",q)); + } + /* There's 16 bytes of something after all of that, don't know + what it is though - incorrectly documented */ + + DEBUG(4,("lookupsid line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use ?! */ + qSSVAL(0); /* undocumented */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + qunihdr(sidtostring(sids[i])); + DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qunistr(sidtostring(sids[i])); + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSALOOKUPNAMES: + DEBUG(1,("LSALOOKUPNAMES\n")); + q = data + 0x18; + policyhandle = q; q += 20; + nentries = qIVAL; + DEBUG(4,("lookupnames entries %d\n",nentries)); + q += 4; /* skip second count */ + q += 8 * nentries; /* skip pointers */ + for (nnames = 0; nnames < nentries; nnames++) + { + names[nnames] = q; /* set name string to unicode header */ + q += IVAL(q,0)*2; /* guessing here */ + } + /* There's a translated sids structure next but it looks fals */ + + DEBUG(4,("lookupnames line %d\n",__LINE__)); + /* formulate reply */ + q = *rdata + 0x18; + qSIVAL(2); /* bufptr */ + qSIVAL(4); /* number of referenced domains + - need one per each identifier authority in call */ + qSIVAL(2); /* dom bufptr */ + qSIVAL(32); /* max entries */ + qSIVAL(4); /* number of reference domains? */ + + qunihdr(lp_workgroup()); /* reference domain */ + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-1"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-5"); + qSIVAL(2); /* sid bufptr */ + + qunihdr("S-1-3"); + qSIVAL(2); /* sid bufptr */ + + qunistr(lp_workgroup()); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + + strcpy(domsid,lp_domainsid()); + p = strtok(domsid+2,"-"); + revision = atoi(p); + identauth = atoi(strtok(0,"-")); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-1"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ + DEBUG(4,("lookupsid line %d\n",__LINE__)); + + qunistr("S-1-5"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + + qunistr("S-1-3"); + qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + + qSIVAL(nentries); + qSIVAL(2); /* bufptr */ + qSIVAL(nentries); + DEBUG(4,("lookupnames line %d\n",__LINE__)); + for (i = 0; i < nentries; i++) + { + qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ + qSSVAL(5); /* undocumented */ + DEBUG(4,("lookupnames line %d\n",__LINE__)); + qSIVAL(nametorid(names[i])); + DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); + qSIVAL(0); /* domain index out of above reference domains */ + } + qSIVAL(nentries); /* mapped count */ + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + default: + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + } + return(True); +} + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + char *domainname; + int domlen; + pstring domsid; + char *p; + int numsubauths; + int subauths[MAXSUBAUTHS]; + struct smb_passwd *smb_pass; /* To check if machine account exists */ + pstring machacct; + pstring foo; + uint16 infoclass; + uint16 revision; /* Domain sid revision */ + int identauth; + int i; + char *logonsrv; + char *unicomp; + char *accountname; + uint16 secchanneltype; + uint32 negflags; + char netcred[8]; + uint32 rcvcred[8]; + char rtncred[8]; + uint32 clnttime; + uint32 rtntime; + char *newpass; + uint16 logonlevel; + uint16 switchval; + uint16 dommaxlen; + uint16 paramcontrol; + uint32 logonid[2]; + uint16 usernamelen; + uint16 usernamemaxlen; + uint16 wslen; + uint16 wsmaxlen; + uchar *rc4lmowfpass; + uchar *rc4ntowfpass; + char *domain; + char *username; + char *ws; + struct uinfo *userinfo; + int pkttype; + ArcfourContext c; + uchar rc4key[16]; + uchar ntowfpass[16]; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("netlogon LINE %d\n",__LINE__)); + switch (opnum) + { + case LSAREQCHAL: + DEBUG(1,("LSAREQCHAL\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ + q = skip_unicode_string(logonsrv,1) + 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + + + DEBUG(1,("logonsrv=%s unicomp=%s\n", + unistr(logonsrv), + unistr(unicomp))); + + dcauth[cnum].chal[0] = IVAL(q, 0); + dcauth[cnum].chal[1] = IVAL(q, 4); + dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ + dcauth[cnum].cred[1] = IVAL(q, 4); + +DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); + + /* PAXX: set these to random values */ + dcauth[cnum].svrchal[0] = 0x11111111; + dcauth[cnum].svrchal[1] = 0x22222222; + dcauth[cnum].svrcred[0] = 0x11111111; + dcauth[cnum].svrcred[1] = 0x22222222; + strcpy(machacct,unistr(unicomp)); + strcat(machacct, "$"); + smb_pass = get_smbpwnam(machacct); + if(smb_pass) + memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); + DEBUG(1,("pass %s %s\n", machacct, foo)); + setsesskey(cnum); + q = *rdata + 0x18; + qSIVAL(dcauth[cnum].svrchal[0]); + qSIVAL(dcauth[cnum].svrchal[1]); + +DEBUG(1,("NL: server challenge %08x %08x\n", + dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSAAUTH2: + DEBUG(1,("LSAAUTH2\n")); + dump_data(1,q,128); + q = data + 0x18; + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + dump_data(1,unicomp,32); + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + q = align4(q, data); + negflags = qIVAL; + DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), + rcvcred[0], rcvcred[1], negflags)); + +DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", + rcvcred[0], rcvcred[1], negflags)); + + checkcred(cnum, rcvcred[0], rcvcred[1], 0); + q = *rdata + 0x18; + makecred(cnum, 0, q); + q += 8; + + qSIVAL(negflags); + /* update stored client credentials */ + dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; + dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + + case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } + + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); + } + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) + { + /* put the extra sids: PAXX: TODO */ + } + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); + DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); + DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); + DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) + { + qSIVAL(subauths[i]); + } + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) + q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; + default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); + default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + } + return(True); +} + +static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char calccred[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].cred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + if (IVAL(calccred,0) != cred0 || + IVAL(calccred,4) != cred1) + { + DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); + /* PAXX: do something about it! */ + } else + DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", + cred0, cred1, time, + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].cred[0], dcauth[cnum].cred[1], + IVAL(calccred,0), IVAL(calccred,4))); +} + +static void makecred(int cnum, uint32 time, char *calccred) +{ + uint32 sum[2]; + char netdata[8]; + char netsesskey[8]; + char icv[8]; + char key2[7]; + + SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); + SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); + SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); + SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); + E1(netsesskey,netdata,icv); + memset(key2, 0, sizeof key2); + key2[0] = netsesskey[7]; + E1(key2, icv, calccred); + DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", + dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], + dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], + dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], + IVAL(calccred, 0), IVAL(calccred, 4))); +} + +static void setsesskey(int cnum) +{ + uint32 sum[2]; + char netsum[8]; + char netsesskey[8]; + char icv[8]; + + sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; + sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; + SIVAL(netsum,0,sum[0]); + SIVAL(netsum,4,sum[1]); + E1(dcauth[cnum].md4pw,netsum,icv); + E1(dcauth[cnum].md4pw+9,icv,netsesskey); + dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); + dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); + +DEBUG(1,("NL: session key %08x %08x\n", + dcauth[cnum].sesskey[0], + dcauth[cnum].sesskey[1])); +} + +static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) +{ + static struct uinfo u; + static pstring fullnm; + static pstring ascuser; + extern pstring myname; + static pstring stme; + static pstring stdom; + struct smb_passwd *smb_pass; + + strcpy(ascuser,unistr(user)); + ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ + DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); + + smb_pass = get_smbpwnam(ascuser); + if(!smb_pass) + return 0; + DEBUG(1,("GETU %d\n", __LINE__)); + if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { + DEBUG(1,("pass mismatch:\n")); + dump_data(1,ntowfpass,16); + dump_data(1,smb_pass->smb_nt_passwd,16); + return 0; + } + + DEBUG(1,("GETU %d\n", __LINE__)); + u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; + u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; + u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; + u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; + u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; + DEBUG(1,("GETU %d\n", __LINE__)); + u.effectivename = ascuser; + strcpy(fullnm, "Full name of "); + strcat(fullnm, ascuser); + DEBUG(1,("GETU %d\n", __LINE__)); + u.fullname = fullnm; + u.logonscript = "foologin.cmd"; + u.profilepath = "prof"; + u.homedirectory = "foohomes"; + DEBUG(1,("GETU %d\n", __LINE__)); + u.homedirectorydrive = "a:"; + u.logoncount = 7; + u.badpwcount = 8; + u.uid = 778; + DEBUG(1,("GETU %d\n", __LINE__)); + u.gid = 998; + u.ngroups = 2; + u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); + u.groups[0].gid = 776; + DEBUG(1,("GETU %d\n", __LINE__)); + u.groups[0].attr = 0x7; + u.groups[1].gid = 776; + u.groups[1].attr = 0x7; + u.userflags = 0x20; + u.logonserver = stme; + get_myname(myname,NULL); + strcpy(stme, myname); + strupper(stme); + DEBUG(1,("LS %s\n", u.logonserver)); + u.logondomain = stdom; + strcpy(stdom, lp_workgroup()); + strupper(stdom); + DEBUG(1,("DOM %s\n", u.logondomain)); + u.nsids = 0; + u.sids = 0; + DEBUG(1,("GETU %d\n", __LINE__)); + return &u; +}; + + #endif /* NTDOMAIN */ diff --git a/source/smbd/server.c b/source/smbd/server.c index d387b7375bb..1c31f69389d 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -3003,7 +3003,8 @@ static int sig_hup() Setup the groups a user belongs to. ****************************************************************************/ int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups) + int **p_igroups, gid_t **p_groups, + int **p_attrs) { if (-1 == initgroups(user,gid)) { @@ -3018,19 +3019,25 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, { int i,ngroups; int *igroups; + int *attrs; gid_t grp = 0; ngroups = getgroups(0,&grp); if (ngroups <= 0) ngroups = 32; igroups = (int *)malloc(sizeof(int)*ngroups); + attrs = (int *)malloc(sizeof(int)*ngroups); for (i=0;i<ngroups;i++) + { + attrs [i] = 0x7; /* XXXX don't know what NT user attributes are yet! */ igroups[i] = 0x42424242; + } ngroups = getgroups(ngroups,(gid_t *)igroups); if (igroups[0] == 0x42424242) ngroups = 0; *p_ngroups = ngroups; + *p_attrs = attrs; /* The following bit of code is very strange. It is due to the fact that some OSes use int* and some use gid_t* for @@ -3052,16 +3059,18 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups, groups_use_ints = False; if (groups_use_ints) - { + { *p_igroups = igroups; *p_groups = (gid_t *)igroups; - } + } else - { + { gid_t *groups = (gid_t *)igroups; igroups = (int *)malloc(sizeof(int)*ngroups); for (i=0;i<ngroups;i++) + { igroups[i] = groups[i]; + } *p_igroups = igroups; *p_groups = (gid_t *)groups; } @@ -3270,12 +3279,15 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de /* groups stuff added by ih */ pcon->ngroups = 0; + pcon->igroups = NULL; pcon->groups = NULL; + pcon->attrs = NULL; if (!IS_IPC(cnum)) { /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); + setup_groups(pcon->user,pcon->uid,pcon->gid, + &pcon->ngroups,&pcon->igroups,&pcon->groups,&pcon->attrs); /* check number of connections */ if (!claim_connection(cnum, diff --git a/source/smbd/uid.c b/source/smbd/uid.c index cdc4e474c61..78614a5b5c4 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -227,13 +227,17 @@ BOOL become_user(int cnum, uint16 vuid) if (Connections[cnum].force_user || lp_security() == SEC_SHARE || !(vuser) || (vuser->guest) || - !check_user_ok(cnum,vuser,snum)) { + !check_user_ok(cnum,vuser,snum)) + { uid = Connections[cnum].uid; gid = Connections[cnum].gid; current_user.groups = Connections[cnum].groups; current_user.igroups = Connections[cnum].igroups; current_user.ngroups = Connections[cnum].ngroups; - } else { + current_user.attrs = vuser->attrs; + } + else + { if (!vuser) { DEBUG(2,("Invalid vuid used %d\n",vuid)); return(False); @@ -243,9 +247,10 @@ BOOL become_user(int cnum, uint16 vuid) gid = vuser->gid; else gid = Connections[cnum].gid; - current_user.groups = vuser->user_groups; - current_user.igroups = vuser->user_igroups; - current_user.ngroups = vuser->user_ngroups; + current_user.ngroups = vuser->n_groups; + current_user.groups = vuser->groups; + current_user.igroups = vuser->igroups; + current_user.attrs = vuser->attrs; } if (initial_uid == 0) -- cgit From 5e521438292472c816527d4ee7c6dff7e3c217ea Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Fri, 10 Oct 1997 16:12:27 +0000 Subject: I have to admit that I'm not very good at writing Makefiles. This one will simply create an object file from each of the .c files in the directory. These could be linked into a static library, but I'm not sure that this is worthwhile. If anyone wants to improved on what I've got here, please do! crh -)----- --- source/ubiqx/Makefile | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 source/ubiqx/Makefile diff --git a/source/ubiqx/Makefile b/source/ubiqx/Makefile new file mode 100644 index 00000000000..16fb454e77d --- /dev/null +++ b/source/ubiqx/Makefile @@ -0,0 +1,32 @@ +########################################################################### +# Makefile for ubiqx libraries under Samba. +# Copyright Chris Hertel & the Samba Team 1997 +########################################################################### + +.SUFFIXES: +.SUFFIXES: .c .o .h + +all: ubi_AVLtree.o ubi_BinTree.o ubi_SplayTree.o ubi_dLinkList.o + +ubi_BinTree.o: ubi_BinTree.h + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + +ubi_AVLtree.o: ubi_AVLtree.h ubi_BinTree.h + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + +ubi_SplayTree.o: ubi_SplayTree.h ubi_BinTree.h + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + +ubi_dLinkList.o: ubi_dLinkList.h + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + +.c.o: + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + +clean: + rm -f core *.o *~ -- cgit From e2e1979b6215080593728942d414a273505877df Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 16:40:23 +0000 Subject: ipc.c : #if NTDOMAIN call to api_netlogRPC #endif lsaparse.c : renamed lsa_io_q_auth2 to lsa_io_q_auth_2. pipes.c : added api_lsa_reply_auth_2() and api_netlogRPC. proto.h : the usual. --- source/include/proto.h | 2 +- source/lsaparse.c | 2 +- source/smbd/ipc.c | 2 + source/smbd/pipes.c | 1366 ++++++++++++++---------------------------------- 4 files changed, 397 insertions(+), 975 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 94937daade4..0ed52bc6fde 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -331,7 +331,7 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align); char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align); char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align); -char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align); +char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align); char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align); char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align); char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align); diff --git a/source/lsaparse.c b/source/lsaparse.c index 9ea6f566b23..b515901ab54 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -244,7 +244,7 @@ char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int a /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align) +char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align) { if (q_a == NULL) return NULL; diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 28cdb22889a..6b255dd405e 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2765,6 +2765,8 @@ struct { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, #ifdef NTDOMAIN { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, + { "SetNmdPpHndState", "NETLOGON", 1, api_netlogrpcTNP }, #else { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, #endif diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 5a6da643d98..24f15ba7fd8 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -753,15 +753,15 @@ static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, - char resp_cred[8], NEG_FLAGS *flgs, int status) + DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) { - make_lsa_chal(&(r_a->srv_chal), resp_cred); - memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); + memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); + memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); r_a->status = status; } static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, - char resp_cred[8], int status) + DOM_CHAL *resp_cred, int status) { char *start = q; LSA_R_AUTH_2 r_a; @@ -1185,63 +1185,67 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, return True; } -static void api_lsa_req_chal( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) +static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) { - int reply_len; - + struct smb_passwd *smb_pass = get_smbpwnam(mach_acct); int i; - LSA_Q_REQ_CHAL q_r; - - fstring mach_acct; - struct smb_passwd *smb_pass; - - /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); - fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr2(q_r.uni_logon_srv .buffer), - mach_acct)); - - strcat(mach_acct, "$"); - - smb_pass = get_smbpwnam(mach_acct); if (smb_pass != NULL) { - memcpy(vuser->dc.md4pw, smb_pass->smb_nt_passwd, sizeof(vuser->dc.md4pw)); + memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); } else { /* No such machine account. Should error out here, but we'll print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", mach_acct)); + DEBUG(1,("No account in domain for %s\n", mach_acct)); + return False; } { char foo[16]; - for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", vuser->dc.md4pw[i]); - DEBUG(1,("pass %s %s\n", mach_acct, foo)); + for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); + DEBUG(4,("pass %s %s\n", mach_acct, foo)); } /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), - vuser->dc.md4pw, vuser->dc.sess_key); + cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), + dc->md4pw, dc->sess_key); /* copy the client credentials for later use */ - memcpy(vuser->dc.srv_chal.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); - memcpy(vuser->dc.srv_cred.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); /* create a server challenge for the client */ /* PAXX: set these to random values. */ /* lkcl: paul, you mentioned that it doesn't really matter much */ for (i = 0; i < 8; i++) { - vuser->dc.srv_chal.data[i] = 0xA5; + dc->srv_chal.data[i] = 0xA5; } + return True; +} + +static void api_lsa_req_chal( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + + LSA_Q_REQ_CHAL q_r; + + fstring mach_acct; + + /* grab the challenge... */ + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + + fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); + + strcat(mach_acct, "$"); + + update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct); + /* construct reply. return status is always 0x0 */ reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, &(vuser->dc.srv_chal)); @@ -1252,976 +1256,392 @@ static void api_lsa_req_chal( user_struct *vuser, *rdata_len = reply_len; } -void no_fn(uint uid) +static void api_lsa_auth_2( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) { - user_struct *vuser = get_valid_user_struct(uid); - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif -} + int reply_len; + LSA_Q_AUTH_2 q_a; -#endif /* NTDOMAIN */ + DOM_CHAL srv_chal; + UTIME srv_time; + + srv_time.time = 0; + + /* grab the challenge... */ + lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4); + + /* check that the client credentials are valid */ + cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, + &(vuser->dc.srv_cred), srv_time); + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_chal); + + /* construct reply. return status is always 0x0 */ + reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, + &srv_chal, 0x0); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - uchar rc4key[16]; - uchar ntowfpass[16]; - uint32 nentries; - char *policyhandle; - #define MAXSIDS 64 - uchar *sids[MAXSIDS]; /* for lookup SID */ - int nsids; - #define MAXNAMES 64 - uchar *names[MAXNAMES]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) - { - case LSAOPENPOLICY: - DEBUG(1,("LSAOPENPOLICY\n")); - char *q = *rdata + 0x18; - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - /* return a 20 byte policy handle */ - /* here's a pretty handle:- */ - qSIVAL(time(NULL)); - qSIVAL(0x810a792f); - qSIVAL(0x11d107d5); - qSIVAL(time(NULL)); - qSIVAL(0x6cbcf800); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */ - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - break; - - case LSAQUERYINFOPOLICY: - DEBUG(1,("LSAQUERYINFOPOLICY\n")); - dump_data(1,data,128); - infoclass = SVAL(data, 44); /* also a policy handle but who cares? */ - q = *rdata + 0x18; - qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose - value is ignored */ - qSSVAL(infoclass); - domainname = lp_workgroup(); - domlen = strlen(domainname); - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q)); - - switch (infoclass) - { - case 5: - case 3: - default: - qSSVAL(0); /* 2 undocumented bytes */ - qSSVAL(domlen*2); - qSSVAL(domlen*2); /* unicode domain len and maxlen */ - qSIVAL(4); /* domain buffer pointer */ - qSIVAL(2); /* domain sid pointer */ - qunistr(domainname); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - } - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAENUMTRUSTDOM: - DEBUG(1,("LSAENUMTRUSTDOM\n")); - q = *rdata + 0x18; - qSIVAL(0); /* enumeration context */ - qSIVAL(0); /* entries read */ - qSIVAL(0); /* trust information */ - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - break; - - case LSACLOSE: - DEBUG(1,("LSACLOSE\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; + user_struct *vuser = get_valid_user_struct(uid); - case LSAOPENSECRET: - DEBUG(1,("LSAOPENSECRET\n")); - q = *rdata + 0x18; - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - qSIVAL(0); - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - break; + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } - case LSALOOKUPSIDS: - DEBUG(1,("LSAOPENSECRET\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupsid entries %d\n",nentries)); - q += (2+nentries) * 4; /* skip bufptrs */ - /* now we have nentries sids of the form: - uint32 Subauthority count (SAC) - char Revision - char Subaurity count again - char[6] Identifier authority - [uint32 subauthority] * SAC - */ - for (nsids = 0; nsids < nentries; nsids++) - { - DEBUG(4,("lookupsid q in %lx\n",q)); - sids[nsids] = q; - DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0))); - q += 4+1+1+6+IVAL(q,0)*4; - DEBUG(4,("lookupsid q %lx\n",q)); - } - /* There's 16 bytes of something after all of that, don't know - what it is though - incorrectly documented */ - - DEBUG(4,("lookupsid line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + if (vuser == NULL) return False; - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ + switch (opnum) + { + case LSA_REQCHAL: + { + DEBUG(3,("LSA_REQCHAL\n")); + api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + break; + } - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use ?! */ - qSSVAL(0); /* undocumented */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - qunihdr(sidtostring(sids[i])); - DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qunistr(sidtostring(sids[i])); - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; + case LSA_AUTH2: + { + DEBUG(3,("LSA_AUTH2\n")); + api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + break; + } - case LSALOOKUPNAMES: - DEBUG(1,("LSALOOKUPNAMES\n")); - q = data + 0x18; - policyhandle = q; q += 20; - nentries = qIVAL; - DEBUG(4,("lookupnames entries %d\n",nentries)); - q += 4; /* skip second count */ - q += 8 * nentries; /* skip pointers */ - for (nnames = 0; nnames < nentries; nnames++) - { - names[nnames] = q; /* set name string to unicode header */ - q += IVAL(q,0)*2; /* guessing here */ - } - /* There's a translated sids structure next but it looks fals */ - - DEBUG(4,("lookupnames line %d\n",__LINE__)); - /* formulate reply */ - q = *rdata + 0x18; - qSIVAL(2); /* bufptr */ - qSIVAL(4); /* number of referenced domains - - need one per each identifier authority in call */ - qSIVAL(2); /* dom bufptr */ - qSIVAL(32); /* max entries */ - qSIVAL(4); /* number of reference domains? */ - - qunihdr(lp_workgroup()); /* reference domain */ - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-1"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-5"); - qSIVAL(2); /* sid bufptr */ - - qunihdr("S-1-3"); - qSIVAL(2); /* sid bufptr */ - - qunistr(lp_workgroup()); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - - strcpy(domsid,lp_domainsid()); - p = strtok(domsid+2,"-"); - revision = atoi(p); - identauth = atoi(strtok(0,"-")); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - DEBUG(4,("lookupsid line %d\n",__LINE__)); + default: + { + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + break; + } + } - qunistr("S-1-1"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */ - DEBUG(4,("lookupsid line %d\n",__LINE__)); + return True; +} - qunistr("S-1-5"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */ - qunistr("S-1-3"); - qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */ +#if 0 - qSIVAL(nentries); - qSIVAL(2); /* bufptr */ - qSIVAL(nentries); - DEBUG(4,("lookupnames line %d\n",__LINE__)); - for (i = 0; i < nentries; i++) - { - qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */ - qSSVAL(5); /* undocumented */ - DEBUG(4,("lookupnames line %d\n",__LINE__)); - qSIVAL(nametorid(names[i])); - DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i]))); - qSIVAL(0); /* domain index out of above reference domains */ - } - qSIVAL(nentries); /* mapped count */ - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; +case LSASVRPWSET: + DEBUG(1,("LSASVRPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; + +case LSASAMLOGON: + DEBUG(1,("LSASAMLOGON\n")); + dump_data(1,data,128); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(logonsrv,1)+16; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1)+4; + DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", + __LINE__, unistr(logonsrv), unistr(unicomp))); + q = align4(q, data); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 2; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + + q += 6; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + + usernamelen = qSVAL; + + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + + DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", + usernamelen, usernamemaxlen, dommaxlen)); + + dump_data(1,q,128); + + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + + q += 12; domain = q; q += dommaxlen + 12; + q = align4(q, data); + username = q; q += usernamemaxlen + 12; + q = align4(q, data); + ws = q; + DEBUG(1,("domain=%s username=%s ws=%s\n", + unistr(domain), unistr(username), + unistr(ws))); + break; + default: + DEBUG(0,("unknown switch in SAMLOGON %d\n", + switchval)); + } + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); + DEBUG(1,("userNAME %s [%s]\n", foo, username)); + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = *rdata + 0x18; + qSIVAL(0x16a4b4); /* magic buffer pointer ? */ + makecred(cnum, clnttime+1, q); + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + q += 8; + qSIVAL(0); /* timestamp. client doesn't care */ + qSSVAL(3); /* switch value 3. May be others? */ + qSSVAL(0); /* undocumented */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + + memset(rc4key, 0, sizeof rc4key); + SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); + SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); + DEBUG(1,("rc4ntowf %s\n", foo)); + arcfour_init(&c, rc4key, sizeof rc4key); + arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); + for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); + DEBUG(1,("ntowf %s\n", foo)); + + if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { + qSIVAL(0); /* no buffer */ + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); + break; + } - default: - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + qSIVAL(2); /* another magic bufptr? */ + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); + qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); + qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); + DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); + qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); + qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); + qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); + qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); + DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); + qunihdr(userinfo->effectivename); + qunihdr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunihdr(userinfo->logonscript); + qunihdr(userinfo->profilepath); + qunihdr(userinfo->homedirectory); + qunihdr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSSVAL(userinfo->logoncount); + qSSVAL(userinfo->badpwcount); + qSIVAL(userinfo->uid); + qSIVAL(userinfo->gid); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + qSIVAL(8); /* ptr to groups */ + qSIVAL(userinfo->userflags); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ + qunihdr(userinfo->logonserver); + qunihdr(userinfo->logondomain); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(2); /* logon domain id ptr */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + memset(q,0,40); q += 40; /* expansion room */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->nsids); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(0); /* ptr to sids and values */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->effectivename); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->fullname); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->logonscript); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qunistr(userinfo->profilepath); + qunistr(userinfo->homedirectory); + qunistr(userinfo->homedirectorydrive); + DEBUG(1,("SMLOG %d\n", __LINE__)); + qSIVAL(userinfo->ngroups); + for (i = 0; i < userinfo->ngroups; i++) + { + qSIVAL(userinfo->groups[i].gid); + qSIVAL(userinfo->groups[i].attr); } - return(True); -} - - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - char *domainname; - int domlen; - pstring domsid; - char *p; - int numsubauths; - int subauths[MAXSUBAUTHS]; - struct smb_passwd *smb_pass; /* To check if machine account exists */ - pstring machacct; - pstring foo; - uint16 infoclass; - uint16 revision; /* Domain sid revision */ - int identauth; - int i; - char *logonsrv; - char *unicomp; - char *accountname; - uint16 secchanneltype; - uint32 negflags; - char netcred[8]; - uint32 rcvcred[8]; - char rtncred[8]; - uint32 clnttime; - uint32 rtntime; - char *newpass; - uint16 logonlevel; - uint16 switchval; - uint16 dommaxlen; - uint16 paramcontrol; - uint32 logonid[2]; - uint16 usernamelen; - uint16 usernamemaxlen; - uint16 wslen; - uint16 wsmaxlen; - uchar *rc4lmowfpass; - uchar *rc4ntowfpass; - char *domain; - char *username; - char *ws; - struct uinfo *userinfo; - int pkttype; - ArcfourContext c; - uchar rc4key[16]; - uchar ntowfpass[16]; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ + qunistr(userinfo->logonserver); + qunistr(userinfo->logondomain); + for (i = 0; i < userinfo->nsids; i++) { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; + /* put the extra sids: PAXX: TODO */ } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("netlogon LINE %d\n",__LINE__)); - switch (opnum) + /* Assumption. This is the only domain, sending our SID */ + /* PAXX: may want to do passthrough later */ + strcpy(domsid,lp_domainsid()); +DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + revision = atoi(p); +DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); + identauth = atoi(strtok(0,"-")); +DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); + numsubauths = 0; + while (p = strtok(0, "-")) + subauths[numsubauths++] = atoi(p); + qSIVAL(numsubauths); + qSCVAL(revision); + qSCVAL(numsubauths); + qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ + qRSIVAL(identauth); /* next 4 bytes */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + for (i = 0; i < numsubauths; i++) { - case LSAREQCHAL: - DEBUG(1,("LSAREQCHAL\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */ - q = skip_unicode_string(logonsrv,1) + 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - - - DEBUG(1,("logonsrv=%s unicomp=%s\n", - unistr(logonsrv), - unistr(unicomp))); - - dcauth[cnum].chal[0] = IVAL(q, 0); - dcauth[cnum].chal[1] = IVAL(q, 4); - dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */ - dcauth[cnum].cred[1] = IVAL(q, 4); - -DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1])); - - /* PAXX: set these to random values */ - dcauth[cnum].svrchal[0] = 0x11111111; - dcauth[cnum].svrchal[1] = 0x22222222; - dcauth[cnum].svrcred[0] = 0x11111111; - dcauth[cnum].svrcred[1] = 0x22222222; - strcpy(machacct,unistr(unicomp)); - strcat(machacct, "$"); - smb_pass = get_smbpwnam(machacct); - if(smb_pass) - memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16); - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]); - DEBUG(1,("pass %s %s\n", machacct, foo)); - setsesskey(cnum); - q = *rdata + 0x18; - qSIVAL(dcauth[cnum].svrchal[0]); - qSIVAL(dcauth[cnum].svrchal[1]); - -DEBUG(1,("NL: server challenge %08x %08x\n", - dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1])); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSAAUTH2: - DEBUG(1,("LSAAUTH2\n")); - dump_data(1,q,128); - q = data + 0x18; - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - dump_data(1,unicomp,32); - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - q = align4(q, data); - negflags = qIVAL; - DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), - rcvcred[0], rcvcred[1], negflags)); - -DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n", - rcvcred[0], rcvcred[1], negflags)); - - checkcred(cnum, rcvcred[0], rcvcred[1], 0); - q = *rdata + 0x18; - makecred(cnum, 0, q); - q += 8; - - qSIVAL(negflags); - /* update stored client credentials */ - dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0]; - dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1]; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - - case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); - DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); - DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); - DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - - case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) - q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; - default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); - default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + qSIVAL(subauths[i]); } - return(True); -} - -static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char calccred[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].cred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].cred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - if (IVAL(calccred,0) != cred0 || - IVAL(calccred,4) != cred1) - { - DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); - /* PAXX: do something about it! */ - } else - DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n", - cred0, cred1, time, - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].cred[0], dcauth[cnum].cred[1], - IVAL(calccred,0), IVAL(calccred,4))); -} + qSCVAL(1); /* Authoratitive. Change if passthrough? */ + qSCVAL(0); /* pad for above boolean */ + qSSVAL(0); /* pad for above boolean */ + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + +case LSASAMLOGOFF: + DEBUG(1,("LSASAMLOGOFF\n")); + q = data + 0x18; + logonsrv = q + 16; + DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); + unicomp = skip_unicode_string(logonsrv,1)+16; + if (strlen(unistr(logonsrv)) % 2 == 0) +q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + q = skip_unicode_string(unicomp,1)+4; + if (strlen(unistr(unicomp)) % 2 == 0) +q += 2; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[0] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + rcvcred[1] = qIVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + clnttime = qIVAL; + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + q += 4; + rtncred[0] = qIVAL; /* all these are ignored */ + DEBUG(1,("SMLOG %d\n", __LINE__)); + rtncred[1] = qIVAL; + rtntime = qIVAL; + logonlevel = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + switchval = qSVAL; + switch (switchval) + { + case 1: + q += 4; + domlen = qSVAL; + dommaxlen = qSVAL; q += 4; + paramcontrol = qIVAL; + logonid[0] = qIVAL; /* low part */ + logonid[1] = qIVAL; /* high part */ + usernamelen = qSVAL; + DEBUG(1,("SMLOG %d\n", __LINE__)); + usernamemaxlen = qSVAL; q += 4; + wslen = qSVAL; + wsmaxlen = qSVAL; q += 4; + rc4lmowfpass = q; q += 16; + rc4ntowfpass = q; q += 16; + q += 12; domain = q; q += dommaxlen + 12; + if ((domlen/2) % 2 != 0) q += 2; + username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ + if ((usernamelen/2) % 2 != 0) q += 2; + ws = q; + break; +default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); + } + DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); +default: + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); -static void makecred(int cnum, uint32 time, char *calccred) -{ - uint32 sum[2]; - char netdata[8]; - char netsesskey[8]; - char icv[8]; - char key2[7]; - - SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time); - SIVAL(netdata, 4, dcauth[cnum].svrcred[1]); - SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]); - SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]); - E1(netsesskey,netdata,icv); - memset(key2, 0, sizeof key2); - key2[0] = netsesskey[7]; - E1(key2, icv, calccred); - DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n", - dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1], - dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1], - dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1], - IVAL(calccred, 0), IVAL(calccred, 4))); -} +#endif /* 0 */ -static void setsesskey(int cnum) +void no_fn(uint uid) { - uint32 sum[2]; - char netsum[8]; - char netsesskey[8]; - char icv[8]; - - sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0]; - sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1]; - SIVAL(netsum,0,sum[0]); - SIVAL(netsum,4,sum[1]); - E1(dcauth[cnum].md4pw,netsum,icv); - E1(dcauth[cnum].md4pw+9,icv,netsesskey); - dcauth[cnum].sesskey[0] = IVAL(netsesskey,0); - dcauth[cnum].sesskey[1] = IVAL(netsesskey,4); - -DEBUG(1,("NL: session key %08x %08x\n", - dcauth[cnum].sesskey[0], - dcauth[cnum].sesskey[1])); } -static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass) -{ - static struct uinfo u; - static pstring fullnm; - static pstring ascuser; - extern pstring myname; - static pstring stme; - static pstring stdom; - struct smb_passwd *smb_pass; - - strcpy(ascuser,unistr(user)); - ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */ - DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len)); - - smb_pass = get_smbpwnam(ascuser); - if(!smb_pass) - return 0; - DEBUG(1,("GETU %d\n", __LINE__)); - if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) { - DEBUG(1,("pass mismatch:\n")); - dump_data(1,ntowfpass,16); - dump_data(1,smb_pass->smb_nt_passwd,16); - return 0; - } - - DEBUG(1,("GETU %d\n", __LINE__)); - u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff; - u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff; - u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff; - u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff; - u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff; - DEBUG(1,("GETU %d\n", __LINE__)); - u.effectivename = ascuser; - strcpy(fullnm, "Full name of "); - strcat(fullnm, ascuser); - DEBUG(1,("GETU %d\n", __LINE__)); - u.fullname = fullnm; - u.logonscript = "foologin.cmd"; - u.profilepath = "prof"; - u.homedirectory = "foohomes"; - DEBUG(1,("GETU %d\n", __LINE__)); - u.homedirectorydrive = "a:"; - u.logoncount = 7; - u.badpwcount = 8; - u.uid = 778; - DEBUG(1,("GETU %d\n", __LINE__)); - u.gid = 998; - u.ngroups = 2; - u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2)); - u.groups[0].gid = 776; - DEBUG(1,("GETU %d\n", __LINE__)); - u.groups[0].attr = 0x7; - u.groups[1].gid = 776; - u.groups[1].attr = 0x7; - u.userflags = 0x20; - u.logonserver = stme; - get_myname(myname,NULL); - strcpy(stme, myname); - strupper(stme); - DEBUG(1,("LS %s\n", u.logonserver)); - u.logondomain = stdom; - strcpy(stdom, lp_workgroup()); - strupper(stdom); - DEBUG(1,("DOM %s\n", u.logondomain)); - u.nsids = 0; - u.sids = 0; - DEBUG(1,("GETU %d\n", __LINE__)); - return &u; -}; +#endif /* NTDOMAIN */ +#ifdef UNDEFINED_NTDOMAIN +/* + PAXX: Someone fix above. + The above API is indexing RPC calls based on RPC flags and + fragment length. I've decided to do it based on operation number :-) +*/ #endif /* NTDOMAIN */ -- cgit From 0d043cfef289ee82287bb6014a164ba83ca87f30 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 18:03:30 +0000 Subject: added lsa_reply_srv_pwset() --- source/include/smb.h | 2 +- source/smbd/pipes.c | 162 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 97 insertions(+), 67 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 87fcb22cac9..62351da187e 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -282,7 +282,7 @@ typedef fstring string; #define LSA_QUERYINFOPOLICY 0x07 #define LSA_ENUMTRUSTDOM 0x0d #define LSA_REQCHAL 0x04 -#define LSA_SVRPWSET 0x06 +#define LSA_SRVPWSET 0x06 #define LSA_SAMLOGON 0x02 #define LSA_AUTH2 0x0f #define LSA_CLOSE 0x00 diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 24f15ba7fd8..0a94be0aa0a 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -747,11 +747,6 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, return q - start; } -static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) -{ - memcpy(cred->data, resp_cred, sizeof(cred->data)); -} - static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) { @@ -777,22 +772,22 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) +static void make_lsa_dom_chal(DOM_CRED *cred, DOM_CHAL *srv_chal, UTIME srv_time) { - make_lsa_chal(&(cred->challenge), srv_chal); + memcpy(cred->challenge.data, srv_chal->data, sizeof(srv_chal->data)); cred->timestamp = srv_time; } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - char srv_chal[8], UTIME srv_time, int status) + DOM_CHAL *srv_chal, UTIME srv_time, int status) { make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); r_a->status = status; } static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, int status) { char *start = q; @@ -922,7 +917,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, LSA_USER_INFO *user_info) { char *start = q; @@ -946,7 +941,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, + DOM_CHAL *srv_cred, UTIME srv_time, uint32 status) { char *start = q; @@ -1276,9 +1271,9 @@ static void api_lsa_auth_2( user_struct *vuser, &(vuser->dc.srv_cred), srv_time); /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_chal); + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); - /* construct reply. return status is always 0x0 */ + /* construct reply. */ reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, &srv_chal, 0x0); @@ -1289,6 +1284,87 @@ static void api_lsa_auth_2( user_struct *vuser, } +static void api_lsa_srv_pwset( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SRV_PWSET q_a; + + DOM_CHAL srv_chal; + UTIME srv_time; + UTIME new_clnt_time; + + srv_time.time = 0; + + /* grab the challenge... */ + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + + /* check that the client credentials are valid */ + cred_assert(&(q_a.clnt_id.cred.challenge), vuser->dc.sess_key, + &(vuser->dc.srv_cred), srv_time); + + new_clnt_time.time = q_a.clnt_id.cred.timestamp.time + 1; + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &srv_chal); + + *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + + /* construct reply. always indicate failure. nt keeps going... */ + reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, + &srv_chal, srv_time, + NT_STATUS_WRONG_PASSWORD|0xC000000); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; +} + +#if 0 +case LSASRVPWSET: + DEBUG(1,("LSASRVPWSET\n")); + q = data + 0x18; + dump_data(1,q,128); + logonsrv = q + 16; + q = skip_unicode_string(logonsrv,1)+12; + q = align4(q, data); + accountname = q; + q = skip_unicode_string(accountname,1); + secchanneltype = qSVAL; + q += 12; + q = align4(q, data); + unicomp = q; + q = skip_unicode_string(unicomp,1); + rcvcred[0] = qIVAL; + rcvcred[1] = qIVAL; + clnttime = qIVAL; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp))); + + checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); + DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); + newpass = q; + + DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", + unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + + /* PAXX: For the moment we'll reject these */ + /* TODO Need to set newpass in smbpasswd file for accountname */ + q = *rdata + 0x18; + makecred(cnum, clnttime+1, q); + q += 8; + qSIVAL(0); /* timestamp. Seems to be ignored */ + + dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + + endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); + break; +#endif + + BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1331,6 +1407,13 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, break; } + case LSA_SRVPWSET: + { + DEBUG(3,("LSA_SRVPWSET\n")); + api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + break; + } + default: { DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); @@ -1344,46 +1427,6 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, #if 0 -case LSASVRPWSET: - DEBUG(1,("LSASVRPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); - - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; - - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); - - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; - case LSASAMLOGON: DEBUG(1,("LSASAMLOGON\n")); dump_data(1,data,128); @@ -1631,17 +1674,4 @@ default: #endif /* 0 */ -void no_fn(uint uid) -{ -} - -#endif /* NTDOMAIN */ - -#ifdef UNDEFINED_NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - #endif /* NTDOMAIN */ -- cgit From 75f32987d8599d10b294dc4e0c0160eecda7296b Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 19:48:51 +0000 Subject: added api_lsa_sam_logon() and api_sam_logoff(). that's it. lots of run-time debugging, now. --- source/smbd/pipes.c | 386 +++++++++++++++++++++++++++++----------------------- 1 file changed, 216 insertions(+), 170 deletions(-) diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 0a94be0aa0a..e6c29fadf6f 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -772,29 +772,21 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return q - start; } -static void make_lsa_dom_chal(DOM_CRED *cred, DOM_CHAL *srv_chal, UTIME srv_time) -{ - memcpy(cred->challenge.data, srv_chal->data, sizeof(srv_chal->data)); - cred->timestamp = srv_time; -} - - static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - DOM_CHAL *srv_chal, UTIME srv_time, int status) + DOM_CRED *srv_cred, int status) { - make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); + memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); r_a->status = status; } static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, - int status) + DOM_CRED *srv_cred, int status) { char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ - make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); + make_lsa_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); @@ -917,15 +909,14 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, - LSA_USER_INFO *user_info) + DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); /* store the user information, if there is any. */ r_s.user = user_info; @@ -941,7 +932,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - DOM_CHAL *srv_cred, UTIME srv_time, + DOM_CRED *srv_cred, uint32 status) { char *start = q; @@ -949,7 +940,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* XXXX maybe we want to say 'no', reject the client's credentials */ r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); r_s.status = status; @@ -1284,36 +1275,52 @@ static void api_lsa_auth_2( user_struct *vuser, } -static void api_lsa_srv_pwset( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) +static BOOL deal_with_credentials(user_struct *vuser, + DOM_CRED *clnt_cred, DOM_CRED *srv_cred) { - int reply_len; - LSA_Q_SRV_PWSET q_a; - - DOM_CHAL srv_chal; - UTIME srv_time; UTIME new_clnt_time; - srv_time.time = 0; - - /* grab the challenge... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + /* doesn't matter that server time is 0 */ + srv_cred->timestamp.time = 0; /* check that the client credentials are valid */ - cred_assert(&(q_a.clnt_id.cred.challenge), vuser->dc.sess_key, - &(vuser->dc.srv_cred), srv_time); + if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, + &(vuser->dc.srv_cred), clnt_cred->timestamp)) + { + return False; + } - new_clnt_time.time = q_a.clnt_id.cred.timestamp.time + 1; + /* increment client time by one second */ + new_clnt_time.time = clnt_cred->timestamp.time + 1; /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &srv_chal); + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, + &(srv_cred->challenge)); + /* update the client and server credentials, for use next time... */ *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + return True; +} + +static void api_lsa_srv_pwset( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SRV_PWSET q_a; + + DOM_CRED srv_cred; + + /* grab the challenge and encrypted password ... */ + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); + /* construct reply. always indicate failure. nt keeps going... */ reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, - &srv_chal, srv_time, + &srv_cred, NT_STATUS_WRONG_PASSWORD|0xC000000); /* construct header, now that we know the reply length */ @@ -1322,111 +1329,133 @@ static void api_lsa_srv_pwset( user_struct *vuser, *rdata_len = reply_len; } -#if 0 -case LSASRVPWSET: - DEBUG(1,("LSASRVPWSET\n")); - q = data + 0x18; - dump_data(1,q,128); - logonsrv = q + 16; - q = skip_unicode_string(logonsrv,1)+12; - q = align4(q, data); - accountname = q; - q = skip_unicode_string(accountname,1); - secchanneltype = qSVAL; - q += 12; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1); - rcvcred[0] = qIVAL; - rcvcred[1] = qIVAL; - clnttime = qIVAL; - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp))); +static void api_lsa_sam_logoff( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + int reply_len; + LSA_Q_SAM_LOGOFF q_l; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags)); - newpass = q; + DOM_CRED srv_cred; + + /* grab the challenge... */ + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4); - DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n", - unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass)); + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); - /* PAXX: For the moment we'll reject these */ - /* TODO Need to set newpass in smbpasswd file for accountname */ - q = *rdata + 0x18; - makecred(cnum, clnttime+1, q); - q += 8; - qSIVAL(0); /* timestamp. Seems to be ignored */ - - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; + /* construct reply. always indicate success */ + reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18, + &srv_cred, + 0x0); - endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len); - break; -#endif + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len; +} -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) + +static void api_lsa_sam_logon( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) { - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); + int reply_len; + LSA_Q_SAM_LOGON q_l; + LSA_USER_INFO usr_info; + LSA_USER_INFO *p_usr_info = NULL; - user_struct *vuser = get_valid_user_struct(uid); + DOM_CRED srv_creds; - if (pkttype == 0x0b) /* RPC BIND */ + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); + + if (vuser != NULL) { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } + NTTIME dummy_time; + pstring logon_script; + pstring profile_path; + pstring home_dir; + pstring home_drive; + pstring my_name; + pstring my_workgroup; + pstring dom_sid; + pstring username; + extern pstring myname; + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + get_myname(myname, NULL); + + pstrcpy(logon_script, lp_logon_script()); + pstrcpy(profile_path, lp_logon_path ()); + pstrcpy(dom_sid , lp_domainsid ()); + pstrcpy(my_workgroup, lp_workgroup ()); + + pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); + pstrcpy(my_name , myname ); + strupper(my_name); + + pstrcpy(home_drive , "a:" ); + +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + pstrcpy(home_dir , vuser->home_share); +#else + pstrcpy(home_dir , "\\\\%L\\%U"); + standard_sub_basic(home_dir); +#endif - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + p_usr_info = &usr_info; - if (vuser == NULL) return False; + make_lsa_user_info(p_usr_info, - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ - switch (opnum) - { - case LSA_REQCHAL: - { - DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(vuser, param, data, rdata, rdata_len); - break; - } + username, /* user_name */ + vuser->real_name, /* full_name */ + logon_script, /* logon_script */ + profile_path, /* profile_path */ + home_dir, /* home_dir */ + home_drive, /* dir_drive */ - case LSA_AUTH2: - { - DEBUG(3,("LSA_AUTH2\n")); - api_lsa_auth_2(vuser, param, data, rdata, rdata_len); - break; - } + 0, /* logon_count */ + 0, /* bad_pw_count */ - case LSA_SRVPWSET: - { - DEBUG(3,("LSA_SRVPWSET\n")); - api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); - break; - } + vuser->uid, /* uint32 user_id */ + vuser->gid, /* uint32 group_id */ + 0, /* uint32 num_groups */ + NULL, /* DOM_GID *gids */ + 0x20, /* uint32 user_flgs */ - default: - { - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - break; - } + NULL, /* char sess_key[16] */ + + my_name, /* char *logon_srv */ + my_workgroup, /* char *logon_dom */ + + dom_sid, /* char *dom_sid */ + NULL); /* char *other_sids */ } - return True; + reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18, + &srv_creds, p_usr_info); + + /* construct header, now that we know the reply length */ + reply_len += make_rpc_reply(data, *rdata, reply_len); + + *rdata_len = reply_len; } #if 0 - case LSASAMLOGON: DEBUG(1,("LSASAMLOGON\n")); dump_data(1,data,128); @@ -1616,62 +1645,79 @@ DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); break; +#endif -case LSASAMLOGOFF: - DEBUG(1,("LSASAMLOGOFF\n")); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SAMLOGOFF %d\n", __LINE__)); - unicomp = skip_unicode_string(logonsrv,1)+16; - if (strlen(unistr(logonsrv)) % 2 == 0) -q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(unicomp,1)+4; - if (strlen(unistr(unicomp)) % 2 == 0) -q += 2; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 4; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - q += 4; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - usernamelen = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - q += 12; domain = q; q += dommaxlen + 12; - if ((domlen/2) % 2 != 0) q += 2; - username = q; q += usernamemaxlen + 12; /* PAXX: HACK */ - if ((usernamelen/2) % 2 != 0) q += 2; - ws = q; - break; -default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval)); - } - DEBUG(1,("SAMLOGOFF %s\n", unistr(username))); -default: - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); + + user_struct *vuser = get_valid_user_struct(uid); + + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } -#endif /* 0 */ + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + + if (vuser == NULL) return False; + + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif + + switch (opnum) + { + case LSA_REQCHAL: + { + DEBUG(3,("LSA_REQCHAL\n")); + api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_AUTH2: + { + DEBUG(3,("LSA_AUTH2\n")); + api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SRVPWSET: + { + DEBUG(3,("LSA_SRVPWSET\n")); + api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SAMLOGON: + { + DEBUG(3,("LSA_SAMLOGON\n")); + api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); + break; + } + + case LSA_SAMLOGOFF: + { + DEBUG(3,("LSA_SAMLOGOFF\n")); + api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len); + break; + } + + default: + { + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + break; + } + } + + return True; +} #endif /* NTDOMAIN */ -- cgit From 2ade5b2706b884fbca2a5794912280a58bc41a08 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 10 Oct 1997 19:49:17 +0000 Subject: the usual --- source/include/proto.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/include/proto.h b/source/include/proto.h index 0ed52bc6fde..93458bcaf9c 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -642,7 +642,10 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -void no_fn(uint uid); +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); /*The following definitions come from predict.c */ -- cgit From 832a05825476d6d5d80245e28f490104b4d84c99 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Fri, 10 Oct 1997 22:59:43 +0000 Subject: Updating for 1.9.17p3 release. Jeremy (jallison@whistle.com) --- WHATSNEW.txt | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index fa3600d6c35..b3aa7d78a17 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,52 @@ - WHATS NEW IN 1.9.17p2 - September 26th 1997 + WHATS NEW IN 1.9.17p2 - October 13th 1997 =========================================== +Update release: Samba - version 1.9.17p3. +----------------------------------------- + +This is the latest stable release of Samba. This is the +version that all production Samba servers should be running +for all current bug-fixes. + +Here are a list of the fixes in this release (the fixes +introduced between 1.9.17p2 and 1.9.17p3) : + +1). Truncation of long browse lists. +2). Crash bug when dead share mode memory entries need removing. +3). Race condition in slow share mode code. +4). Potential buffer overflow from password server. +5). Fix for read-prediction growing read-only files. +6). Many quota code fixes. +7). Fix for spelling mistake in attack warning :-). +8). Removed 'ERRbaddirectory' error code - caused problem with + Visual Basic apps. +9). Allow 'hosts allow/deny' to work before client packet parsed. +10). Wrapping log file causes incorrect errors to be returned to + the clients. +11). Crash fix for nmbd Get_Hostbyname bad return. + +Reporting bugs +-------------- + +The Samba Team believes that this is a stable +production release, but all software has bugs. +If you have problems, or think you have found a +bug please email a report to : + +samba-bugs@samba.anu.edu.au + +Stating the version number of Samba that you +are running, and *full details* of the steps +we need to reproduce the problem. + +As always, all bugs are our responsibility. + +Regards, + + The Samba Team. + +-------------Previous release notes------------------------- + Security fix release: Samba - version 1.9.17p2. ---------------------------------------------- -- cgit From bbbe907cc41ad25a9c013d2254384b399f7c36d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Fri, 10 Oct 1997 23:02:49 +0000 Subject: Added Luke's changes to release tree. Jeremy (jallison@whistle.com) --- docs/textdocs/BROWSING.txt | 155 +++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt index d8362f15299..4e0a49f2202 100644 --- a/docs/textdocs/BROWSING.txt +++ b/docs/textdocs/BROWSING.txt @@ -8,8 +8,8 @@ Summary: This describes how to configure Samba for improved browsing. OVERVIEW: ========= SMB networking provides a mechanism by which clients can access a list -of machines that are available within the network. This list is called -the browse list and is heavily used by all SMB clients. Configuration +of machines that are available within the network. This list is called +the browse list and is heavily used by all SMB clients. Configuration of SMB browsing has been problematic for some Samba users, hence this document. @@ -17,7 +17,7 @@ document. BROWSING ======== -Samba now fully supports browsing. The browsing is supported by nmbd +Samba now fully supports browsing. The browsing is supported by nmbd and is also controlled by options in the smb.conf file (see smb.conf(5)). Samba can act as a local browse master for a workgroup and the ability @@ -28,10 +28,13 @@ Samba can also act as a domain master browser for a workgroup. This means that it will collate lists from local browse masters into a wide area network server list. In order for browse clients to resolve the names they may find in this list, it is recommended that -both samba and your clients use a WINS server +both samba and your clients use a WINS server. Note that you should NOT set Samba to be the domain master for a -workgroup that has the same name as an NT Domain. +workgroup that has the same name as an NT Domain: on each wide area +network, you must only ever have one domain master browser per workgroup, +regardless of whether it is NT, Samba or any other type of domain master +that is providing this service. [Note that nmbd can be configured as a WINS server, but it is not necessary to specifically use samba as your WINS server. NTAS can @@ -48,10 +51,10 @@ Samba becomes a part of. Samba also has a useful option for a Samba server to offer itself for browsing on another subnet. It is recommended that this option is only used for 'unusual' purposes: announcements over the internet, for -example. See "remote announce" in the smb.conf man page. +example. See "remote announce" in the smb.conf man page. If something doesn't work then hopefully the log.nmb file will -help you track down the problem. Try a debug level of 2 or 3 for +help you track down the problem. Try a debug level of 2 or 3 for finding problems. Note that if it doesn't work for you, then you should still be able to @@ -59,14 +62,14 @@ type the server name as \\SERVER in filemanager then hit enter and filemanager should display the list of available shares. Some people find browsing fails because they don't have the global -"guest account" set to a valid account. Remember that the IPC$ +"guest account" set to a valid account. Remember that the IPC$ connection that lists the shares is done as guest, and thus you must have a valid guest account. Also, a lot of people are getting bitten by the problem of too many -parameters on the command line of nmbd in inetd.conf. This trick is to +parameters on the command line of nmbd in inetd.conf. This trick is to not use spaces between the option and the parameter (eg: -d2 instead -of -d 2), and to not use the -B and -N options. New versions of nmbd +of -d 2), and to not use the -B and -N options. New versions of nmbd are now far more likely to correctly find your broadcast and network addess, so in most cases these aren't needed. @@ -74,23 +77,23 @@ The other big problem people have is that their broadcast address, netmask or IP address is wrong (specified with the "interfaces" option in smb.conf) + BROWSING ACROSS SUBNETS ======================= -With the release of Samba 1.9.17(alpha1 and above) Samba has been -updated to enable it to support the replication of browse lists -across subnet boundaries. New code and options have been added to -achieve this. This section describes how to set this feature up -in different settings. +With the release of Samba 1.9.17, Samba has been updated to enable +it to support the replication of browse lists across subnet +boundaries. New code and options have been added to achieve this. +This section describes how to set this feature up in different settings. -To see browse lists that span TCP/IP subnets (ie. networks separated +To see browse lists that span TCP/IP subnets (ie. networks separated by routers that don't pass broadcast traffic) you must set up at least -one WINS server. The WINS server acts as a DNS for NetBIOS names, allowing +one WINS server. The WINS server acts as a DNS for NetBIOS names, allowing NetBIOS name to IP address translation to be done by doing a direct -query of the WINS server. This is done via a directed UDP packet on -port 137 to the WINS server machine. The reason for a WINS server is +query of the WINS server. This is done via a directed UDP packet on +port 137 to the WINS server machine. The reason for a WINS server is that by default, all NetBIOS name to IP address translation is done -by broadcasts from the querying machine. This means that machines +by broadcasts from the querying machine. This means that machines on one subnet will not be able to resolve the names of machines on another subnet without using a WINS server. @@ -104,7 +107,7 @@ How does cross subnet browsing work ? ===================================== Cross subnet browsing is a complicated dance, containing multiple -moving parts. It has taken Microsoft several years to get the code +moving parts. It has taken Microsoft several years to get the code that achieves this correct, and Samba lags behind in some areas. However, with the 1.9.17 release, Samba is capable of cross subnet browsing when configured correctly. @@ -127,38 +130,38 @@ Consider a network set up as follows : (WINS) Consisting of 3 subnets (1, 2, 3) conneted by two routers -(R1, R2) - these do not pass broadcasts. Subnet 1 has 5 machines -on it, subnet 2 has 4 machines, subnet 3 has 4 machines. Assume +(R1, R2) - these do not pass broadcasts. Subnet 1 has 5 machines +on it, subnet 2 has 4 machines, subnet 3 has 4 machines. Assume for the moment that all these machines are configured to be in the -same workgroup (for simplicities sake). Machine N1_C on subnet 1 -is configured as Domain Master Browser (ie. it will collate the -browse lists for the workgroup). Machine N2_D is configured as +same workgroup (for simplicities sake). Machine N1_C on subnet 1 +is configured as Domain Master Browser (ie. it will collate the +browse lists for the workgroup). Machine N2_D is configured as WINS server and all the other machines are configured to register their NetBIOS names with it. As all these machines are booted up, elections for master browsers -will take place on each of the three subnets. Assume that machine +will take place on each of the three subnets. Assume that machine N1_C wins on subnet 1, N2_B wins on subnet 2, and N3_D wins on subnet 3 - these machines are known as local master browsers for -their particular subnet. N1_C has an advantage in winning as the +their particular subnet. N1_C has an advantage in winning as the local master browser on subnet 1 as it is set up as Domain Master Browser. On each of the three networks, machines that are configured to offer sharing services will broadcast that they are offering -these services. The local master browser on each subnet will +these services. The local master browser on each subnet will receive these broadcasts and keep a record of the fact that -the machine is offering a service. This list of records is -the basis of the browse list. For this case, assume that +the machine is offering a service. This list of records is +the basis of the browse list. For this case, assume that all the machines are configured to offer services so all machines will be on the browse list. For each network, the local master browser on that network is considered 'authoritative' for all the names it receives via -local broadcast. This is because a machine seen by the local +local broadcast. This is because a machine seen by the local master browser via a local broadcast must be on the same network as the local master browser and thus is a 'trusted' -and 'verifiable' resource. Machines on other networks that +and 'verifiable' resource. Machines on other networks that the local master browsers learn about when collating their browse lists have not been directly seen - these records are called 'non-authoritative'. @@ -178,21 +181,21 @@ Subnet3 N3_D N3_A, N3_B, N3_C, N3_D Note that at this point all the subnets are separate, no machine is seen across any of the subnets. -Now examine subnet 2. As soon as N2_B has become the local +Now examine subnet 2. As soon as N2_B has become the local master browser it looks for a Domain master browser to synchronize -its browse list with. It does this by querying the WINS server +its browse list with. It does this by querying the WINS server (N2_D) for the IP address associated with the NetBIOS name -WORKGROUP<1B>. This name was registerd by the Domain master +WORKGROUP<1B>. This name was registerd by the Domain master browser (N1_C) with the WINS server as soon as it was booted. Once N2_B knows the address of the Domain master browser it tells it that is the local master browser for subnet 2 by sending a MasterAnnouncement packet as a UDP port 138 packet. -It then synchronizes with it by doing a NetServerEnum2 call. This +It then synchronizes with it by doing a NetServerEnum2 call. This tells the Domain Master Browser to send it all the server -names it knows about. Once the domain master browser receives +names it knows about. Once the domain master browser receives the MasterAnnouncement packet it schedules a synchronization -request to the sender of that packet. After both synchronizations +request to the sender of that packet. After both synchronizations are done the browse lists look like : Subnet Browse Master List @@ -212,10 +215,10 @@ subnets 1 or 2 will see all the servers on both, users on subnet 3 will still only see the servers on their own subnet. The same sequence of events that occured for N2_B now occurs -for the local master browser on subnet 3 (N3_D). When it +for the local master browser on subnet 3 (N3_D). When it synchronizes browse lists with the domain master browser (N1_A) it gets both the server entries on subnet 1, and those on -subnet 2. After N3_D has synchronized with N1_C and vica-versa +subnet 2. After N3_D has synchronized with N1_C and vica-versa the browse lists look like. Subnet Browse Master List @@ -239,7 +242,7 @@ subnet 2 will still only see the servers on subnets 1 and 2, but not 3. Finally, the local master browser for subnet 2 (N2_B) will sync again with the domain master browser (N1_C) and will recieve the missing -server entries. Finally - and as a steady state (if no machines +server entries. Finally - and as a steady state (if no machines are removed or shut off) the browse lists will look like : Subnet Browse Master List @@ -273,36 +276,36 @@ names will not be removed from the network neighbourhood lists. 3) If one of the fragments is cut off from the WINS server, it will only be able to access servers on its local subnet, by using subnet-isolated -broadcast NetBIOS name resolution. The effects are similar to that of +broadcast NetBIOS name resolution. The effects are similar to that of losing access to a DNS server. Setting up a WINS server ======================== Either a Samba machine or a Windows NT Server machine may be set up -as a WINS server. To set a Samba machine to be a WINS server you must +as a WINS server. To set a Samba machine to be a WINS server you must add the following option to the smb.conf file on the selected machine : in the [globals] section add the line wins support = yes Versions of Samba previous to 1.9.17 had this parameter default to -yes. If you have any older versions of Samba on your network it is +yes. If you have any older versions of Samba on your network it is strongly suggested you upgrade to 1.9.17 or above, or at the very least set the parameter to 'no' on all these machines. Machines with "wins support = yes" will keep a list of all NetBIOS names registered with them, acting as a DNS for NetBIOS names. -You should set up only ONE wins server. Do NOT set the +You should set up only ONE wins server. Do NOT set the "wins support = yes" option on more than one Samba server. To set up a Windows NT Server as a WINS server you need to set up -the WINS service - see your NT documentation for details. Note that +the WINS service - see your NT documentation for details. Note that Windows NT WINS Servers can replicate to each other, allowing more -than one to be set up in a complex subnet environment. As Microsoft +than one to be set up in a complex subnet environment. As Microsoft refuse to document these replication protocols Samba cannot currently -participate in these replications. It is possible in the future that +participate in these replications. It is possible in the future that a Samba->Samba WINS replication protocol may be defined, in which case more than one Samba machine could be set up as a WINS server but currently only one Samba server should have the "wins support = yes" @@ -310,10 +313,10 @@ parameter set. After the WINS server has been configured you must ensure that all machines participating on the network are configured with the address -of this WINS server. If your WINS server is a Samba machine, fill in +of this WINS server. If your WINS server is a Samba machine, fill in the Samba machine IP address in the "Primary WINS Server" field of the "Control Panel->Network->Protocols->TCP->WINS Server" dialogs -in Windows 95 or Windows NT. To tell a Samba server the IP address +in Windows 95 or Windows NT. To tell a Samba server the IP address of the WINS server add the following line to the [global] section of all smb.conf files : @@ -323,14 +326,14 @@ where <name or IP address> is either the DNS name of the WINS server machine or its IP address. Note that this line MUST NOT BE SET in the smb.conf file of the Samba -server acting as the WINS server itself. If you set both the +server acting as the WINS server itself. If you set both the "wins support = yes" option and the "wins server = <name>" option then nmbd will fail to start. There are two possible scenarios for setting up cross subnet browsing. The first details setting up cross subnet browsing on a network containing Windows 95, Samba and Windows NT machines that are not configured as -part of a Windows NT Domain. The second details setting up cross subnet +part of a Windows NT Domain. The second details setting up cross subnet browsing on networks that contain NT Domains. Setting up Browsing in a WORKGROUP @@ -340,25 +343,23 @@ To set up cross subnet browsing on a network containing machines in up to be in a WORKGROUP, not an NT Domain you need to set up one Samba server to be the Domain Master Browser (note that this is *NOT* the same as a Primary Domain Controller, although in an NT Domain the -same machine plays both roles). The role of a Domain master browser is +same machine plays both roles). The role of a Domain master browser is to collate the browse lists from local master browsers on all the -subnets that have a machine participating in the workgroup. Without +subnets that have a machine participating in the workgroup. Without one machine configured as a domain master browser each subnet would be an isolated workgroup, unable to see any machines on any other -subnet. It is the presense of a domain master browser that makes +subnet. It is the presense of a domain master browser that makes cross subnet browsing possible for a workgroup. In an WORKGROUP environment the domain master browser must be a Samba server, and there must only be one domain master browser per -workgroup name (although the same Samba server can act as Domain -master browser for multiple workgroup names). To set up a Samba -server as a domain master browser set the following option in the -[global] section of the smb.conf file : +workgroup name. To set up a Samba server as a domain master browser, +set the following option in the [global] section of the smb.conf file : domain master = yes The domain master browser should also preferrably be the local master -browser for its own subnet. In order to achieve this set the following +browser for its own subnet. In order to achieve this set the following options in the [global] section of the smb.conf file : domain master = yes @@ -371,9 +372,9 @@ server, if you require. Next, you should ensure that each of the subnets contains a machine that can act as a local master browser for the -workgroup. Any NT machine should be able to do this, as will +workgroup. Any NT machine should be able to do this, as will Windows 95 machines (although these tend to get rebooted more -often, so it's not such a good idea to use these). To make a +often, so it's not such a good idea to use these). To make a Samba server a local master browser set the following options in the [global] section of the smb.conf file : @@ -387,7 +388,7 @@ or they will war with each other over which is to be the local master browser. The "local master" parameter allows Samba to act as a local master -browser. The "preferred master" causes nmbd to force a browser +browser. The "preferred master" causes nmbd to force a browser election on startup and the "os level" parameter sets Samba high enough so that it should win any browser elections. @@ -413,7 +414,7 @@ browser NetBIOS name (DOMAIN<1B>) with WINS instead of the PDC. For subnets other than the one containing the Windows NT PDC you may set up Samba servers as local master browsers as -described. To make a Samba server a local master browser set +described. To make a Samba server a local master browser set the following options in the [global] section of the smb.conf file : @@ -424,8 +425,8 @@ file : If you wish to have a Samba server fight the election with machines on the same subnet you may set the "os level" parameter to lower -levels. By doing this you can tune the order of machines that -will become local master browsers if they are running. For +levels. By doing this you can tune the order of machines that +will become local master browsers if they are running. For more details on this see the section "FORCING SAMBA TO BE THE MASTER" below. @@ -444,17 +445,17 @@ FORCING SAMBA TO BE THE MASTER ============================== Who becomes the "master browser" is determined by an election process -using broadcasts. Each election packet contains a number of parameters +using broadcasts. Each election packet contains a number of parameters which determine what precedence (bias) a host should have in the -election. By default Samba uses a very low precedence and thus loses +election. By default Samba uses a very low precedence and thus loses elections to just about anyone else. If you want Samba to win elections then just set the "os level" global -option in smb.conf to a higher number. It defaults to 0. Using 34 +option in smb.conf to a higher number. It defaults to 0. Using 34 would make it win all elections over every other system (except other samba systems!) -A "os level" of 2 would make it beat WfWg and Win95, but not NTAS. A +A "os level" of 2 would make it beat WfWg and Win95, but not NTAS. A NTAS domain controller uses level 32. The maximum os level is 255 @@ -487,9 +488,9 @@ MAKING SAMBA THE DOMAIN MASTER ============================== The domain master is responsible for collating the browse lists of -multiple subnets so that browsing can occur between subnets. You can +multiple subnets so that browsing can occur between subnets. You can make samba act as the domain master by setting "domain master = yes" -in smb.conf. By default it will not be a domain master. +in smb.conf. By default it will not be a domain master. Note that you should NOT set Samba to be the domain master for a workgroup that has the same name as an NT Domain. @@ -526,13 +527,13 @@ b) when a client receives a domain-wide browse list, and a user attempts to access a host in that list, it will contact the WINS server to resolve the NetBIOS name of that host. as long as that host has registered its NetBIOS name with the same WINS server, the user will - be able to see that host. + be able to see that host. NOTE ABOUT BROADCAST ADDRESSES ============================== If your network uses a "0" based broadcast address (for example if it -ends in a 0) then you will strike problems. Windows for Workgroups +ends in a 0) then you will strike problems. Windows for Workgroups does not seem to support a 0's broadcast and you will probably find that browsing and name lookups won't work. @@ -540,7 +541,7 @@ that browsing and name lookups won't work. MULTIPLE INTERFACES =================== -Samba now supports machines with multiple network interfaces. If you +Samba now supports machines with multiple network interfaces. If you have multiple interfaces then you will need to use the "interfaces" -option in smb.conf to configure them. See smb.conf(5) for details. +option in smb.conf to configure them. See smb.conf(5) for details. -- cgit From 453a543f2ab6b18d505ea6bfc749dc127ab602cf Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Sat, 11 Oct 1997 02:50:55 +0000 Subject: Updated mirrors, combined Sources and Sources&Binaries as our binaries are now with our sources. Have requested that mirror sites remove the old 'binaries' tree. Paul. --- docs/textdocs/MIRRORS.txt | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index c9bd04f1c83..484f0141afa 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -6,23 +6,26 @@ including them on samba.anu.edu.au/pub/samba/Binary_Packages Mirror sites include: -Source Only -=========== ---- Australia --- +--- Austria --- + ftp://gd.tuwien.ac.at/pub/infosys/servers/samba/sources/ +--- Australia --- ftp://samba.anu.edu.au/pub/samba/ - ftp://nimbus.anu.edu.au/pub/tridge/samba/ ftp://choc.satech.net.au/pub/samba/ --- USA Educational --- + ftp://sunsite.unc.edu/pub/packages/samba/sources/ ftp://ftp.micro.caltech.edu/pub/samba/ ftp://ftp.cs.ucr.edu/pub/software/samba/ - ftp://sunsite.unc.edu/pub/Linux/system/Network/samba/ --- Czech Republic --- ftp://sunsite.mff.cuni.cz/Net/Protocols/Samba/ +--- Denmark --- + ftp://sunsite.auc.dk/pub/unix/networking/samba/ --- Germany --- ftp://ftp.uni-trier.de/pub/unix/network/samba/ - ftp://ftp.gwdg.de/pub/server/samba/ --- Greece --- ftp://ftp.ntua.gr/pub/net/samba/ +--- Italy --- + ftp://volftp.tin.it/mirror/samba/pub/samba/ + http://www.inferentia.it/archives/samba/ (no binaries) --- Japan --- ftp://ring.asahi-net.or.jp/archives/net/samba/ ftp://ring.aist.go.jp/archives/net/samba/ @@ -35,28 +38,15 @@ Source Only ftp://despair.capecod.net/pub/Samba/ --- Poland --- ftp://giswitch.sggw.waw.pl/pub/unix/samba/ ---- Portugal --- +--- Potugal --- ftp://ftp.ua.pt/pub/misc/samba/ --- Romania --- - ftp.romus.ro/pub/Linux/Network/samba/ + ftp://ftp.romus.ro/pub/Linux/Network/samba/ --- Russian Federation --- ftp://ftp.uic.nsu.ru/pub/vendors/samba/ --- United Kingdom --- + ftp://sunsite.doc.ic.ac.uk/packages/samba/sources/ ftp://ftp.demon.co.uk/pub/mirrors/samba/ - ftp://src.doc.ic.ac.uk/packages/samba/ - -Sources & Binaries -================== ---- Austria --- - ftp://gd.tuwien.ac.at/pub/infosys/servers/samba/ ---- Denmark --- - ftp://sunsite.auc.dk/pub/unix/networking/samba/ ---- USA Educational --- - ftp://sunsite.unc.edu/pub/packages/samba/ ---- Italy --- - http://www.inferentia.it/archives/samba/ ---- United Kingdom --- - ftp://sunsite.doc.ic.ac.uk/packages/samba/ SCO binaries available from: http://www.math.u-szeged.hu/hardsoft/hsdetail.htm @@ -85,6 +75,5 @@ There are several others. Give archie a try. Http sites include: =================== http://samba.anu.edu.au/samba -http://www.choc.satech.net.au/pub/samba/ - +Japanese - http://samba.bento.ad.jp/ -- cgit From 15a987b9b84293e0c921388b63519e0cf320601f Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Sat, 11 Oct 1997 03:53:53 +0000 Subject: updated Sunsite UK. (Paul) --- docs/textdocs/MIRRORS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index 484f0141afa..339c35a762c 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -45,7 +45,7 @@ Mirror sites include: --- Russian Federation --- ftp://ftp.uic.nsu.ru/pub/vendors/samba/ --- United Kingdom --- - ftp://sunsite.doc.ic.ac.uk/packages/samba/sources/ + ftp://sunsite.doc.ic.ac.uk/packages/samba/ ftp://ftp.demon.co.uk/pub/mirrors/samba/ SCO binaries available from: -- cgit From 1eaad1c99463dcd42eb8ff4ea5686ad9ec6fc42e Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sat, 11 Oct 1997 15:10:57 +0000 Subject: namelogon.c : added NTLOGON. (fixed the case 0:) namepacket.c: call to NTLOGON mailslot nameserv.h defines for NETLOGON and NTLOGON mailslot util.c: added andrew's dump_data() function. --- source/include/nameserv.h | 7 ++ source/include/proto.h | 1 + source/lib/util.c | 38 +++++++ source/namelogon.c | 284 ++++++++++++++++++++++++++++++---------------- source/namepacket.c | 6 + 5 files changed, 238 insertions(+), 98 deletions(-) diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 83f3a3c5246..593c101d92f 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -82,6 +82,7 @@ /* mail slots */ #define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE" #define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON" +#define NT_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NTLOGON" enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL}; enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; @@ -372,6 +373,12 @@ struct packet_struct } packet; }; +/* NETLOGON opcodes */ +#define QUERYFORPDC 7 /* Query for PDC */ +#define QUERYFORPDC_R 12 /* Response to Query for PDC */ +#define SAMLOGON 18 +#define SAMLOGON_R 19 + /* ids for netbios packet types */ #define ANN_HostAnnouncement 1 diff --git a/source/include/proto.h b/source/include/proto.h index 93458bcaf9c..f859e9bfa28 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -1071,3 +1071,4 @@ void pstrcpy(char *dest, char *src); char *align4(char *q, char *base); char *align2(char *q, char *base); char *align_offset(char *q, char *base, int align_offset_len); +void dump_data(int level,unsigned char *buf,int len); diff --git a/source/lib/util.c b/source/lib/util.c index 4e6bfb7054a..208f13aaf00 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4390,3 +4390,41 @@ char *align_offset(char *q, char *base, int align_offset_len) return q; } +static void print_asc(int level, unsigned char *buf,int len) +{ + int i; + for (i=0;i<len;i++) + DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.')); +} + +void dump_data(int level,unsigned char *buf,int len) +{ + int i=0; + if (len<=0) return; + + DEBUG(level,("[%03X] ",i)); + for (i=0;i<len;) { + DEBUG(level,("%02X ",(int)buf[i])); + i++; + if (i%8 == 0) DEBUG(level,(" ")); + if (i%16 == 0) { + print_asc(level,&buf[i-16],8); DEBUG(level,(" ")); + print_asc(level,&buf[i-8],8); DEBUG(level,("\n")); + if (i<len) DEBUG(level,("[%03X] ",i)); + } + } + if (i%16) { + int n; + + n = 16 - (i%16); + DEBUG(level,(" ")); + if (n>8) DEBUG(level,(" ")); + while (n--) DEBUG(level,(" ")); + + n = MIN(8,i%16); + print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" ")); + n = (i%16) - n; + if (n>0) print_asc(level,&buf[i-n],n); + DEBUG(level,("\n")); + } +} diff --git a/source/namelogon.c b/source/namelogon.c index 1f57139d56a..e76c62dee2b 100644 --- a/source/namelogon.c +++ b/source/namelogon.c @@ -29,8 +29,6 @@ extern int ClientDGRAM; -#define TEST_CODE /* want to debug unknown browse packets */ - extern int DEBUGLEVEL; extern pstring myname; @@ -42,104 +40,194 @@ extern pstring myname; **************************************************************************/ void process_logon_packet(struct packet_struct *p,char *buf,int len) { - struct dgram_packet *dgram = &p->packet.dgram; - char *logname,*q; - fstring reply_name; - BOOL add_slashes = False; - pstring outbuf; - int code,reply_code; - char unknown_byte = 0; - uint16 request_count = 0; - uint16 token = 0; - - if (!lp_domain_logons()) - { - DEBUG(3,("No domain logons\n")); - return; - } - - - code = SVAL(buf,0); - switch (code) - { - case 0: - { - char *machine = buf+2; - char *user = skip_string(machine,1); - char *tmp; - logname = skip_string(user,1); - tmp = skip_string(logname,1); - unknown_byte = CVAL(tmp,0); - request_count = SVAL(tmp,1); - token = SVAL(tmp,3); - - reply_code = 0x6; - fstrcpy(reply_name,myname); - strupper(reply_name); - add_slashes = True; - DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - break; - } - case 7: - { - char *machine = buf+2; - logname = skip_string(machine,1); - token = SVAL(skip_string(logname,1),0); - - fstrcpy(reply_name,lp_domain_controller()); - if (!*reply_name) - { - /* oo! no domain controller. must be us, then */ - fstrcpy(reply_name,myname); - reply_code = 0xC; - } - else - { - /* refer logon request to the domain controller */ - reply_code = 0x7; - } - - strupper(reply_name); - DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%x token=%x\n", - machine,inet_ntoa(p->ip), reply_name, reply_code,token)); - break; - } - default: - { - DEBUG(3,("Unknown domain request %d\n",code)); - return; - } - } - - bzero(outbuf,sizeof(outbuf)); - q = outbuf; - SSVAL(q,0,reply_code); - q += 2; - - if (token == 0xffff || /* LM 2.0 or later */ - token == 0xfffe) /* WfWg networking */ - { - if (add_slashes) + struct dgram_packet *dgram = &p->packet.dgram; + pstring my_name; + fstring reply_name; + BOOL add_slashes = False; + pstring outbuf; + int code,reply_code; + char unknown_byte = 0; + uint16 request_count = 0; + uint16 token = 0; + + uint32 ntversion; + uint16 lmnttoken; + uint16 lm20token; + uint32 allowableaccount; /* Control bits, i.e. 0x80 == workstation trust a/c */ + uint32 domainsidsize; + uint16 requestcount; + char *domainsid; + char *uniuser; /* Unicode user name */ + pstring ascuser; + char *mailslot; + char *unicomp; /* Unicode computer name */ + struct smb_passwd *smb_pass; /* To check if machine account exists */ + + if (!lp_domain_logons()) { - strcpy(q,"\\\\"); - q += 2; + DEBUG(3,("No domain logons\n")); + return; } - strcpy(q, reply_name); - strupper(q); - q = skip_string(q,1); - - if (token == 0xffff) /* LM 2.0 or later */ + + strcpy(my_name, myname); + strupper(my_name); + + code = SVAL(buf,0); + DEBUG(1,("namelogon: %x\n", code)); + + switch (code) { - SSVAL(q,0,token); - q += 2; + case 0: + { + char *q = buf + 2; + char *machine = q; + char *user = skip_string(machine,1); + + mailslot = skip_string(user,1); + q = skip_string(mailslot,1); + unknown_byte = CVAL(q,0); + request_count = SVAL(q,1); + token = SVAL(q,3); + + reply_code = 0x6; + strcpy(reply_name,my_name); + add_slashes = True; + + DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", + machine,inet_ntoa(p->ip),user,token)); + + q = outbuf; + SSVAL(q, 0, 6); q += 2; + + strcpy(reply_name, "\\\\"); + strcat(reply_name, my_name); + strcpy(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_reply(True, mailslot, ClientDGRAM, + outbuf,PTR_DIFF(q,outbuf), + my_name,&dgram->source_name.name[0],0x20,0, + p->ip, *iface_ip(p->ip)); + break; + } + + case QUERYFORPDC: + { + char *q = buf + 2; + char *machine = q; + mailslot = skip_string(machine,1); + unicomp = skip_string(mailslot,1); + + q = align2(q, buf); + + q = skip_unicode_string(unicomp,1); + + ntversion = IVAL(q, 0); q += 4; + lmnttoken = SVAL(q, 0); q += 2; + lm20token = SVAL(q, 0); q += 2; + + /* construct reply */ + + q = outbuf; + SSVAL(q, 0, QUERYFORPDC_R); q += 2; + + strcpy(reply_name,my_name); + strcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */ + + q = align2(q, buf); + + PutUniCode(q, my_name); q = skip_unicode_string(q, 1); /* PDC name */ + PutUniCode(q, lp_workgroup()); q = skip_unicode_string(q, 1); /* Domain name. */ + + SIVAL(q, 0, ntversion); q += 4; + SSVAL(q, 0, lmnttoken); q += 2; + SSVAL(q, 0, lm20token); q += 2; + + DEBUG(3,("GETDC request from %s(%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_reply(True, mailslot,ClientDGRAM, + outbuf,PTR_DIFF(q,outbuf), + my_name,&dgram->source_name.name[0],0x20,0, + p->ip, *iface_ip(p->ip)); + return; + } + + case SAMLOGON: + { + char *q = buf + 2; + + requestcount = SVAL(q, 0); q += 2; + unicomp = q; + uniuser = skip_unicode_string(unicomp,1); + mailslot = skip_unicode_string(uniuser,1); + q = skip_string(mailslot,1); + allowableaccount = IVAL(q, 0); q += 4; + domainsidsize = IVAL(q, 0); q += 4; + domainsid = q; + q += domainsidsize + 3; + ntversion = IVAL(q, 0); q += 4; + lmnttoken = SVAL(q, 0); q += 2; + lm20token = SVAL(q, 0); q += 2; + DEBUG(3,("SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); + + /* + If MACHINE$ is in our password database then respond, else ignore. + Let's ignore the SID. + */ + strcpy(ascuser,unistr(uniuser)); + DEBUG(3,("SAMLOGON user %s\n", ascuser)); + strcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER */ + strcpy(reply_name+2,my_name); /* PAXX: Assuming we are logon svr */ + smb_pass = get_smbpwnam(ascuser); + + if(!smb_pass) + { + DEBUG(3,("SAMLOGON request from %s(%s) for %s, not in password file\n", + unistr(unicomp),inet_ntoa(p->ip), ascuser)); + return; + } + else + { + DEBUG(3,("SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", + unistr(unicomp),inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), + SAMLOGON_R ,lmnttoken)); + } + + /* construct reply */ + + q = outbuf; + SSVAL(q, 0, SAMLOGON_R); q += 2; + + PutUniCode(q, reply_name); q = skip_unicode_string(q, 1); + unistrcpy(q, uniuser); q = skip_unicode_string(q, 1); /* User name (workstation trust account) */ + PutUniCode(q, lp_workgroup()); q = skip_unicode_string(q, 1); /* Domain name. */ + + SIVAL(q, 0, ntversion); q += 4; + SSVAL(q, 0, lmnttoken); q += 2; + SSVAL(q, 0, lm20token); q += 2; + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + send_mailslot_reply(True, mailslot,ClientDGRAM, + outbuf,PTR_DIFF(q,outbuf), + my_name,&dgram->source_name.name[0],0x20,0, + p->ip, *iface_ip(p->ip)); + break; + } + + default: + { + DEBUG(3,("Unknown domain request %d\n",code)); + return; + } } - } - - SSVAL(q,0,0xFFFF); - q += 2; - - send_mailslot_reply(True, logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf), - myname,&dgram->source_name.name[0],0x20,0,p->ip, - *iface_ip(p->ip)); + } diff --git a/source/namepacket.c b/source/namepacket.c index 44e449b8c2a..ba2497d7de0 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -386,6 +386,12 @@ static void process_dgram(struct packet_struct *p) process_logon_packet(p,buf2,len); return; } + + /* datagram packet received for the NT domain log on mailslot */ + if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) { + process_logon_packet(p,buf2,len); + return; + } } /**************************************************************************** -- cgit From 1e2fe7c0db0386cb6a007b11ceae53d04e9b8658 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Sat, 11 Oct 1997 16:03:21 +0000 Subject: JHT ==> Luke, your forgot to change the modified date! --- docs/textdocs/BROWSING.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt index cb509647c7e..9cc4a8180db 100644 --- a/docs/textdocs/BROWSING.txt +++ b/docs/textdocs/BROWSING.txt @@ -1,5 +1,5 @@ Author/s: Many (Thanks to Luke, Jeremy, Andrew, etc.) -Updated: June 29, 1997 +Updated: October 12, 1997 Status: Current - For VERY Advanced Users ONLY Summary: This describes how to configure Samba for improved browsing. -- cgit From d2ac9e6fb6e76778154c58217237251d7bb0e98c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 12 Oct 1997 03:48:47 +0000 Subject: remove { and } from the list of illegal characters in filenames. The CIFS3 spec does not list them as illegal. This allows things like the control panel icon to be placed on a Samba drive. --- source/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index b0a45ffb47c..829e307a85b 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -613,7 +613,7 @@ static BOOL illegal_name(char *name) if (!initialised) { - char *ill = "*\\/?<>|\":{}"; + char *ill = "*\\/?<>|\":"; initialised = True; bzero((char *)illegal,256); -- cgit From 732aff735b996a3804ea4d3ca29b4b5f1302d663 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 12 Oct 1997 03:49:29 +0000 Subject: remove { and } from the list of illegal characters in filenames. The CIFS3 spec does not list them as illegal. This allows things like the control panel icon to be placed on a Samba drive. --- source/smbd/mangle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index a964f4a5c73..66e8233df28 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -602,7 +602,7 @@ static BOOL illegal_name(char *name) unsigned char *s; if (!initialised) { - char *ill = "*\\/?<>|\":{}"; + char *ill = "*\\/?<>|\":"; initialised = True; bzero((char *)illegal,256); -- cgit From b1ba290f2ee8c4317e0daf7b6ae18caa82331cc2 Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Sun, 12 Oct 1997 04:40:48 +0000 Subject: Added Finland ftp mirror (PR#175) (Paul) --- docs/textdocs/MIRRORS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index 339c35a762c..66303319e8c 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -19,6 +19,8 @@ Mirror sites include: ftp://sunsite.mff.cuni.cz/Net/Protocols/Samba/ --- Denmark --- ftp://sunsite.auc.dk/pub/unix/networking/samba/ +--- Finland --- + ftp://nic.funet.fi/pub/mirrors/samba.anu.edu.au/ --- Germany --- ftp://ftp.uni-trier.de/pub/unix/network/samba/ --- Greece --- -- cgit From 946d73cf838976b905550288cac3aea7c43959f6 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 12 Oct 1997 11:46:42 +0000 Subject: added debugging macros (suitable eventually for use in tcpdump, hopefully) --- source/include/byteorder.h | 29 +++++++ source/include/proto.h | 37 ++++----- source/lib/util.c | 8 ++ source/lsaparse.c | 198 +++++++++++++++++++++++++++++---------------- source/smbd/pipes.c | 45 ++++++----- 5 files changed, 208 insertions(+), 109 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index 0664a338175..e8989ee7e44 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -198,3 +198,32 @@ it also defines lots of intermediate macros, just ignore those :-) #define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) #define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) +#define DBG_RW_PCVAL(string,depth,base,read,inbuf,outbuf,len) \ + RW_PCVAL(read,inbuf,outbuf,len) \ + DEBUG(5,("%s %04x %s: ", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (inbuf)[idx])); } } \ + DEBUG(5,("\n")); + +#define DBG_RW_PSVAL(string,depth,base,read,inbuf,outbuf,len) \ + RW_PSVAL(read,inbuf,outbuf,len) \ + DEBUG(5,("%s %04x %s: ", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (inbuf)[idx])); } } \ + DEBUG(5,("\n")); + +#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ + RW_CVAL(read,inbuf,outbuf,0) \ + DEBUG(5,("%s %04x %s: %02x\n", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + +#define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \ + RW_SVAL(read,inbuf,outbuf,0) \ + DEBUG(5,("%s %04x %s: %04x\n", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + +#define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \ + RW_IVAL(read,inbuf,outbuf,0) \ + DEBUG(5,("%s %04x %s: %08x\n", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + diff --git a/source/include/proto.h b/source/include/proto.h index f859e9bfa28..d9b6ca157ba 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -322,24 +322,24 @@ BOOL remove_share_oplock(int fnum, share_lock_token token); /*The following definitions come from lsaparse.c */ -char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align); -char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align); -char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align); -char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align); -char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align); -char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align); -char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align); -char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align); -char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align); -char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align); -char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align); -char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align); -char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align); -char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align); -char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align); -char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align); -char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align); -char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align); +char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align, int depth); +char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align, int depth); +char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align, int depth); +char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align, int depth); +char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align, int depth); +char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align, int depth); +char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align, int depth); +char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align, int depth); +char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align, int depth); +char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align, int depth); +char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align, int depth); +char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align, int depth); +char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align, int depth); +char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align, int depth); +char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align, int depth); +char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align, int depth); +char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align, int depth); +char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align, int depth); /*The following definitions come from mangle.c */ @@ -1072,3 +1072,4 @@ char *align4(char *q, char *base); char *align2(char *q, char *base); char *align_offset(char *q, char *base, int align_offset_len); void dump_data(int level,unsigned char *buf,int len); +char *tab_depth(int depth); diff --git a/source/lib/util.c b/source/lib/util.c index 208f13aaf00..a68b8c2e6c1 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4428,3 +4428,11 @@ void dump_data(int level,unsigned char *buf,int len) DEBUG(level,("\n")); } } + +char *tab_depth(int depth) +{ + static pstring spaces; + memset(spaces, ' ', depth * 4); + spaces[depth * 4] = 0; + return spaces; +} diff --git a/source/lsaparse.c b/source/lsaparse.c index b515901ab54..462f621ece9 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -27,13 +27,16 @@ extern int DEBUGLEVEL; /******************************************************************* reads or writes an LSA_R_OPEN_POL structure. ********************************************************************/ -char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align) +char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align, int depth) { if (r_p == NULL) return NULL; + DEBUG(5,("%slsa_io_r_open_pol\n", tab_depth(depth))); + depth++; + q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align); - RW_IVAL(io, q, r_p->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_p->status); q += 4; return q; } @@ -41,13 +44,16 @@ char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int a /******************************************************************* reads or writes an LSA_Q_QUERY_INFO structure. ********************************************************************/ -char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align) +char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align, int depth) { if (q_q == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_query\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = smb_io_pol_hnd(io, &(q_q->pol), q, base, align); - RW_SVAL(io, q, q_q->info_class, 0); q += 2; + DBG_RW_SVAL("info_class", depth, base, io, q, q_q->info_class); q += 2; return q; } @@ -55,15 +61,18 @@ char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int al /******************************************************************* reads or writes an LSA_Q_QUERY_INFO structure. ********************************************************************/ -char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align) +char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align, int depth) { if (r_q == NULL) return NULL; - RW_IVAL(io, q, r_q->undoc_buffer, 0); q += 4; + DEBUG(5,("%s%04x lsa_io_r_query\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_q->undoc_buffer); q += 4; if (r_q->undoc_buffer != 0) { - RW_SVAL(io, q, r_q->info_class, 0); q += 2; + DBG_RW_SVAL("info_class", depth, base, io, q, r_q->info_class); q += 2; switch (r_q->info_class) { @@ -85,7 +94,7 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al } } - RW_IVAL(io, q, r_q->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_q->status); q += 4; return q; } @@ -93,23 +102,28 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align) +char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align, int depth) { int i; if (q_s == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_lookup_sids\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align); /* policy handle */ - RW_IVAL(io, q, q_s->num_entries, 0); q += 4; - RW_IVAL(io, q, q_s->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ - RW_IVAL(io, q, q_s->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ + DBG_RW_IVAL("num_entries", depth, base, io, q, q_s->num_entries); q += 4; + DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, q_s->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ + DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, q_s->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer */ for (i = 0; i < q_s->num_entries; i++) - { - RW_IVAL(io, q, q_s->buffer_lookup_sids[i], 0); q += 4; /* undocumented domain SID pointers to be looked up. */ + { + fstring temp; + sprintf(temp, "buffer_lookup_sids[%d]", i); + DBG_RW_IVAL(temp, depth, base, io, q, q_s->buffer_lookup_sids[i]); q += 4; /* undocumented domain SID pointers to be looked up. */ } for (i = 0; i < q_s->num_entries; i++) @@ -117,7 +131,7 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align); /* domain SIDs to be looked up. */ } - RW_PCVAL(io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ + DBG_RW_PCVAL("undoc", depth, base, io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ return q; } @@ -125,28 +139,31 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align) +char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align, int depth) { int i; if (r_s == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_lookup_sids\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align); /* domain reference info */ - RW_IVAL(io, q, r_s->num_entries, 0); q += 4; - RW_IVAL(io, q, r_s->undoc_buffer, 0); q += 4; - RW_IVAL(io, q, r_s->num_entries2, 0); q += 4; + DBG_RW_IVAL("num_entries", depth, base, io, q, r_s->num_entries); q += 4; + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_s->undoc_buffer); q += 4; + DBG_RW_IVAL("num_entries2", depth, base, io, q, r_s->num_entries2); q += 4; for (i = 0; i < r_s->num_entries2; i++) { q = smb_io_dom_sid2(io, &(r_s->dom_sid[i]), q, base, align); /* domain SIDs being looked up */ } - RW_IVAL(io, q, r_s->num_entries3, 0); q += 4; + DBG_RW_IVAL("num_entries3", depth, base, io, q, r_s->num_entries3); q += 4; - RW_IVAL(io, q, r_s->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_s->status); q += 4; return q; } @@ -154,27 +171,30 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align) +char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align, int depth) { int i; if (q_r == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_lookup_rids\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align); /* policy handle */ - RW_IVAL(io, q, q_r->num_entries, 0); q += 4; - RW_IVAL(io, q, q_r->num_entries2, 0); q += 4; - RW_IVAL(io, q, q_r->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ - RW_IVAL(io, q, q_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ + DBG_RW_IVAL("num_entries", depth, base, io, q, q_r->num_entries); q += 4; + DBG_RW_IVAL("num_entries2", depth, base, io, q, q_r->num_entries2); q += 4; + DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, q_r->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ + DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, q_r->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer */ for (i = 0; i < q_r->num_entries; i++) { q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, 0); /* names to be looked up */ } - RW_PCVAL(io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ + DBG_RW_PCVAL("undoc", depth, base, io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ return q; } @@ -182,28 +202,31 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align) +char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align, int depth) { int i; if (r_r == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_lookup_rids\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align); /* domain reference info */ - RW_IVAL(io, q, r_r->num_entries, 0); q += 4; - RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; - RW_IVAL(io, q, r_r->num_entries2, 0); q += 4; + DBG_RW_IVAL("num_entries", depth, base, io, q, r_r->num_entries); q += 4; + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_r->undoc_buffer); q += 4; + DBG_RW_IVAL("num_entries2", depth, base, io, q, r_r->num_entries2); q += 4; for (i = 0; i < r_r->num_entries2; i++) { q = smb_io_dom_rid2(io, &(r_r->dom_rid[i]), q, base, align); /* domain RIDs being looked up */ } - RW_IVAL(io, q, r_r->num_entries3, 0); q += 4; + DBG_RW_IVAL("num_entries3", depth, base, io, q, r_r->num_entries3); q += 4; - RW_IVAL(io, q, r_r->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_r->status); q += 4; return q; } @@ -211,10 +234,13 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align) +char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align, int depth) { if (q_c == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_req_chal\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align); /* logon server unicode string */ @@ -227,15 +253,18 @@ char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int a /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align) +char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align, int depth) { if (r_c == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_req_chal\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_chal(io, &(r_c->srv_chal), q, base, align); /* server challenge */ - RW_IVAL(io, q, r_c->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_c->status); q += 4; return q; } @@ -244,10 +273,13 @@ char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int a /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align) +char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align, int depth) { if (q_a == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_auth_2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align); /* client identification info */ @@ -260,16 +292,19 @@ char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align) +char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align, int depth) { if (r_a == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_auth_2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_chal (io, &(r_a->srv_chal), q, base, align); /* server challenge */ q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align); - RW_IVAL(io, q, r_a->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_a->status); q += 4; return q; } @@ -278,14 +313,17 @@ char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align) +char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align, int depth) { if (q_s == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_srv_pwset\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_clnt_info(io, &(q_s->clnt_id), q, base, align); /* client identification/authentication info */ - RW_PCVAL(io, q, q_s->pwd, 16); q += 16; /* new password - undocumented */ + DBG_RW_PCVAL("pwd", depth, base, io, q, q_s->pwd, 16); q += 16; /* new password - undocumented */ return q; } @@ -293,15 +331,18 @@ char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align) +char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align, int depth) { if (r_s == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_srv_pwset\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_cred(io, &(r_s->srv_cred), q, base, align); /* server challenge */ - RW_IVAL(io, q, r_s->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_s->status); q += 4; return q; } @@ -311,15 +352,18 @@ char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align) +char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align, int depth) { int i; if (usr == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_user_info\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, usr->undoc_buffer, 0); q += 4; + DBG_RW_IVAL("", depth, base, io, q, usr->undoc_buffer); q += 4; q = smb_io_time(io, &(usr->logon_time) , q, base, align); /* logon time */ q = smb_io_time(io, &(usr->logoff_time) , q, base, align); /* logoff time */ @@ -335,25 +379,25 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align); /* home directory unicode string header */ q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align); /* home directory drive unicode string header */ - RW_SVAL(io, q, usr->logon_count , 0); q += 2; /* logon count */ - RW_SVAL(io, q, usr->bad_pw_count, 0); q += 2; /* bad password count */ + DBG_RW_SVAL("logon_count", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ + DBG_RW_SVAL("bad_pw_count", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ - RW_IVAL(io, q, usr->user_id , 0); q += 4; /* User ID */ - RW_IVAL(io, q, usr->group_id , 0); q += 4; /* Group ID */ - RW_IVAL(io, q, usr->num_groups , 0); q += 4; /* num groups */ - RW_IVAL(io, q, usr->buffer_groups, 0); q += 4; /* undocumented buffer pointer to groups. */ - RW_IVAL(io, q, usr->user_flgs , 0); q += 4; /* user flags */ + DBG_RW_IVAL("user_id", depth, base, io, q, usr->user_id ); q += 4; /* User ID */ + DBG_RW_IVAL("group_id", depth, base, io, q, usr->group_id ); q += 4; /* Group ID */ + DBG_RW_IVAL("num_groups", depth, base, io, q, usr->num_groups ); q += 4; /* num groups */ + DBG_RW_IVAL("buffer_groups", depth, base, io, q, usr->buffer_groups); q += 4; /* undocumented buffer pointer to groups. */ + DBG_RW_IVAL("user_flgs", depth, base, io, q, usr->user_flgs ); q += 4; /* user flags */ - RW_PCVAL(io, q, usr->sess_key, 16); q += 16; /* unused user session key */ + DBG_RW_PCVAL("", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align); /* logon server unicode string header */ q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align); /* logon domain unicode string header */ - RW_IVAL(io, q, usr->buffer_dom_id, 0); q += 4; /* undocumented logon domain id pointer */ - RW_PCVAL(io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ + DBG_RW_IVAL("buffer_dom_id", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ + DBG_RW_PCVAL("padding", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ - RW_IVAL(io, q, usr->num_other_sids, 0); q += 4; /* 0 - num_sids */ - RW_IVAL(io, q, usr->buffer_other_sids, 0); q += 4; /* NULL - undocumented pointer to SIDs. */ + DBG_RW_IVAL("num_other_sids", depth, base, io, q, usr->num_other_sids); q += 4; /* 0 - num_sids */ + DBG_RW_IVAL("buffer_other_sids", depth, base, io, q, usr->buffer_other_sids); q += 4; /* NULL - undocumented pointer to SIDs. */ q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align); /* username unicode string */ q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align); /* user's full name unicode string */ @@ -362,7 +406,7 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align); /* home directory unicode string */ q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align); /* home directory drive unicode string */ - RW_IVAL(io, q, usr->num_groups2, 0); q += 4; /* num groups */ + DBG_RW_IVAL("num_groups2", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ for (i = 0; i < usr->num_groups2; i++) { q = smb_io_gid(io, &(usr->gids[i]), q, base, align); /* group info */ @@ -384,10 +428,13 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align) +char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align, int depth) { if (q_l == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_sam_logon\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ @@ -398,24 +445,27 @@ char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align) +char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align, int depth) { if (r_l == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_sam_logon\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ + DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ - RW_IVAL(io, q, r_l->buffer_user, 0); q += 4; + DBG_RW_IVAL("buffer_user", depth, base, io, q, r_l->buffer_user); q += 4; if (r_l->buffer_user != 0) { - q = lsa_io_user_info(io, r_l->user, q, base, align); + q = lsa_io_user_info(io, r_l->user, q, base, align, depth); } - RW_IVAL(io, q, r_l->auth_resp, 0); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ + DBG_RW_IVAL("auth_resp", depth, base, io, q, r_l->auth_resp); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ - RW_IVAL(io, q, r_l->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_l->status); q += 4; return q; } @@ -423,10 +473,13 @@ char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align) +char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align, int depth) { if (q_l == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_q_sam_logoff\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ @@ -437,16 +490,19 @@ char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, i /******************************************************************* reads or writes a structure. ********************************************************************/ -char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align) +char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align, int depth) { if (r_l == NULL) return NULL; + DEBUG(5,("%s%04x lsa_io_r_sam_logoff\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ + DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ - RW_IVAL(io, q, r_l->status, 0); q += 4; + DBG_RW_IVAL("status", depth, base, io, q, r_l->status); q += 4; return q; } @@ -455,13 +511,13 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i /******************************************************************* reads or writes a structure. ********************************************************************/ - char* lsa_io_(BOOL io, *, char *q, char *base, int align) + char* lsa_io_(BOOL io, *, char *q, char *base, int align, int depth) { if (== NULL) return NULL; q = align_offset(q, base, align); - RW_IVAL(io, q, , 0); q += 4; + DBG_RW_IVAL("", depth, base, io, q, ); q += 4; return q; } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index e6c29fadf6f..3bfee3e3cf1 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -503,15 +503,20 @@ static int make_rpc_reply(char *inbuf, char *q, int data_len) static int lsa_reply_open_policy(char *q, char *base) { + int i; char *start = q; LSA_R_OPEN_POL r_o; /* set up the LSA QUERY INFO response */ - bzero(&(r_o.pol.data), POL_HND_SIZE); + /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ + for (i = 0; i < POL_HND_SIZE; i++) + { + r_o.pol.data[i] = i; + } r_o.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_open_pol(False, &r_o, q, base, 4); + q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -601,7 +606,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, r_q.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_query(False, &r_q, q, base, 4); + q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -697,7 +702,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, r_l.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4); + q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -717,7 +722,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, r_l.status = 0x0; /* store the response in the SMB stream */ - q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4); + q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -741,7 +746,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ - q = lsa_io_r_req_chal(False, &r_c, q, base, 4); + q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -766,7 +771,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); /* store the response in the SMB stream */ - q = lsa_io_r_auth_2(False, &r_a, q, base, 4); + q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -789,7 +794,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, make_lsa_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ - q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); + q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -924,7 +929,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); /* store the response in the SMB stream */ - q = lsa_io_r_sam_logon(False, &r_s, q, base, 4); + q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -945,7 +950,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, r_s.status = status; /* store the response in the SMB stream */ - q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4); + q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ return q - start; @@ -978,7 +983,7 @@ static void api_lsa_query_info( char *param, char *data, pstring dom_sid; /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4); + lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1004,7 +1009,7 @@ static void api_lsa_lookup_sids( char *param, char *data, fstring dom_sids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1038,7 +1043,7 @@ static void api_lsa_lookup_names( char *param, char *data, uint32 dom_rids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1224,7 +1229,7 @@ static void api_lsa_req_chal( user_struct *vuser, fstring mach_acct; /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4); + lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0); fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); @@ -1255,7 +1260,7 @@ static void api_lsa_auth_2( user_struct *vuser, srv_time.time = 0; /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4); + lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0); /* check that the client credentials are valid */ cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, @@ -1313,7 +1318,7 @@ static void api_lsa_srv_pwset( user_struct *vuser, DOM_CRED srv_cred; /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4); + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); @@ -1340,7 +1345,7 @@ static void api_lsa_sam_logoff( user_struct *vuser, DOM_CRED srv_cred; /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); @@ -1368,7 +1373,7 @@ static void api_lsa_sam_logon( user_struct *vuser, DOM_CRED srv_creds; - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4); + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); @@ -1655,7 +1660,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, uint16 opnum = SVAL(data,22); int pkttype = CVAL(data, 2); - user_struct *vuser = get_valid_user_struct(uid); + user_struct *vuser; if (pkttype == 0x0b) /* RPC BIND */ { @@ -1666,7 +1671,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - if (vuser == NULL) return False; + if ((vuser = get_valid_user_struct(uid)) == NULL) return False; DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); #if defined(NETGROUP) && defined(AUTOMOUNT) -- cgit From a6f8de6815e0b85bb23b302980730501ac0b87e5 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 12 Oct 1997 14:17:55 +0000 Subject: ipc.c: debugging info. found that data = NULL because of short packet length indicated from the ntlsaRPC pipe _royally_ stuffs NT's packet handling. maybe this should go down as a service denial bug to the ntbugtraq list. pipes.c lsaparse.c smbparse.c : added more debug stuff. added length of header to data_len in MSRPC fragment_length field (0x18 bytes short) which caused the above bug from NT 4.0. oops. --- source/include/proto.h | 2 +- source/lsaparse.c | 8 +++--- source/smbd/ipc.c | 33 ++++++++++++++---------- source/smbd/pipes.c | 69 ++++++++++++++++++++++++-------------------------- source/smbparse.c | 7 +++-- 5 files changed, 62 insertions(+), 57 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index d9b6ca157ba..1ac4132807e 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -837,7 +837,7 @@ char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align); char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align); char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align); -char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align); +char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, int depth); char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align); diff --git a/source/lsaparse.c b/source/lsaparse.c index 462f621ece9..ee73dd9a056 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -34,7 +34,7 @@ char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int a DEBUG(5,("%slsa_io_r_open_pol\n", tab_depth(depth))); depth++; - q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align); + q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align, depth); DBG_RW_IVAL("status", depth, base, io, q, r_p->status); q += 4; @@ -51,7 +51,7 @@ char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int al DEBUG(5,("%s%04x lsa_io_q_query\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; - q = smb_io_pol_hnd(io, &(q_q->pol), q, base, align); + q = smb_io_pol_hnd(io, &(q_q->pol), q, base, align, depth); DBG_RW_SVAL("info_class", depth, base, io, q, q_q->info_class); q += 2; @@ -113,7 +113,7 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, q = align_offset(q, base, align); - q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align); /* policy handle */ + q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align, depth); /* policy handle */ DBG_RW_IVAL("num_entries", depth, base, io, q, q_s->num_entries); q += 4; DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, q_s->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ @@ -182,7 +182,7 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, q = align_offset(q, base, align); - q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align); /* policy handle */ + q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align, depth); /* policy handle */ DBG_RW_IVAL("num_entries", depth, base, io, q, q_r->num_entries); q += 4; DBG_RW_IVAL("num_entries2", depth, base, io, q, q_r->num_entries2); q += 4; diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 6b255dd405e..b314d416792 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2801,30 +2801,35 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, subcommand = setup[0]; DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); for (i=0;api_fd_commands[i].name;i++) + { if (strequal(api_fd_commands[i].pipename, Files[fd].name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); - break; - } + api_fd_commands[i].subcommand == subcommand && + api_fd_commands[i].fn) + { + DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); + break; + } + } - rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); + rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + DEBUG(10,("calling api_fd_command\n")); + reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, + DEBUG(10,("called api_fd_command\n")); + + if (rdata_len > mdrcnt || rparam_len > mprcnt) + { + reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); - } + } /* if we get False back then it's actually unsupported */ diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 3bfee3e3cf1..820f5965722 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -482,7 +482,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->minor = 0; /* minor version 0 */ hdr->pkt_type = 2; /* RPC response packet */ hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ + hdr->pack_type = 0x10; /* packed data representation */ hdr->frag_len = data_len; /* fragment length, fill in later */ hdr->auth_len = 0; /* authentication length */ hdr->call_id = call_id; /* call identifier - match incoming RPC */ @@ -507,11 +507,18 @@ static int lsa_reply_open_policy(char *q, char *base) char *start = q; LSA_R_OPEN_POL r_o; + static char handle[20] = + { 0x00, 0x00, 0x00, 0x00, + 0x2f, 0x79, 0x0a, 0x81, + 0xd5, 0x17, 0xd1, 0x11, + 0x80, 0xaf, 0x96, 0xcd, + 0x50, 0xf8, 0xbc, 0x6c + }; /* set up the LSA QUERY INFO response */ /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ for (i = 0; i < POL_HND_SIZE; i++) { - r_o.pol.data[i] = i; + r_o.pol.data[i] = handle[i]; } r_o.status = 0x0; @@ -960,24 +967,16 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ - /* return a 20 byte policy handle */ - reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; + /* construct a 20 byte policy handle. return length*/ + *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); } -static void api_lsa_query_info( char *param, char *data, +static int api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; @@ -989,19 +988,13 @@ static void api_lsa_query_info( char *param, char *data, pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, dom_name, dom_sid); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1021,21 +1014,15 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1056,14 +1043,10 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1088,6 +1071,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1096,6 +1081,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1157,6 +1144,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1164,6 +1153,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; } @@ -1657,11 +1648,17 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); - + uint16 opnum; + char pkttype; user_struct *vuser; + DEBUG(5,("api_netlogrpcTNP data:%x\n", data)); + + if (data == NULL) return False; + + opnum = SVAL(data,22); + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ { DEBUG(4,("netlogon rpc bind %x\n",pkttype)); @@ -1669,7 +1666,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, return True; } - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum)); if ((vuser = get_valid_user_struct(uid)) == NULL) return False; diff --git a/source/smbparse.c b/source/smbparse.c index 01438281ef1..0c016c17d9d 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -410,13 +410,16 @@ char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) /******************************************************************* reads or writes an LSA_POL_HND structure. ********************************************************************/ -char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align) +char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, int depth) { if (pol == NULL) return NULL; + DEBUG(5,("%ssmb_io_pol_hnd\n", tab_depth(depth))); + depth++; + q = align_offset(q, base, align); - RW_PCVAL(io, q, pol->data, POL_HND_SIZE); q += POL_HND_SIZE; + DBG_RW_PCVAL("data", depth, base, io, q, pol->data, POL_HND_SIZE); q += POL_HND_SIZE; return q; } -- cgit From 0cf67955f09d99c452bfc3fdde00dcea98e21db1 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 12 Oct 1997 17:07:35 +0000 Subject: updated rpc header reply: callid wrong; alloc hint a uint32 not a uint16. still doesn't get rid of the netlogon trans2 request with zero data. --- source/include/smb.h | 2 +- source/smbd/pipes.c | 36 +++++++++++++++--------------------- source/smbparse.c | 2 +- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 62351da187e..58dfc141bd4 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -477,7 +477,7 @@ typedef struct rpc_hdr_info uint8 minor; /* 0 - RPC minor version */ uint8 pkt_type; /* 2 - RPC response packet */ uint8 frag; /* 3 - first frag + last frag */ - uint32 pack_type; /* 0x0000 0010 - packed data representation */ + uint32 pack_type; /* 0x1000 0000 - packed data representation */ uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */ uint16 auth_len; /* 0 - authentication length */ uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */ diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 820f5965722..4f1d0152168 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -53,10 +53,11 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { - "lsarpc", #if NTDOMAIN "NETLOGON", + "srvsvc", #endif + "lsarpc", NULL }; @@ -494,17 +495,18 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) static int make_rpc_reply(char *inbuf, char *q, int data_len) { - uint32 callid = RIVAL(inbuf, 12); + uint32 callid = IVAL(inbuf, 12); RPC_HDR hdr; + DEBUG(5,("make_rpc_reply. callid: %x\n", callid)); + create_rpc_reply(&hdr, callid, data_len); - return smb_io_rpc_hdr(False, &hdr, q, q, 4) - q; + return PTR_DIFF(smb_io_rpc_hdr(False, &hdr, q, q, 4), q); } static int lsa_reply_open_policy(char *q, char *base) { int i; - char *start = q; LSA_R_OPEN_POL r_o; static char handle[20] = @@ -526,7 +528,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -600,7 +602,6 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { - char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -616,7 +617,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -700,7 +701,6 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -712,7 +712,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static int lsa_reply_lookup_rids(char *q, char *base, @@ -720,7 +720,6 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -732,7 +731,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, @@ -745,7 +744,6 @@ static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { - char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ @@ -756,7 +754,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -770,7 +768,6 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { - char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -781,7 +778,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -794,7 +791,6 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { - char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -804,7 +800,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -923,7 +919,6 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { - char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -939,7 +934,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } @@ -947,7 +942,6 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { - char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -960,7 +954,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } diff --git a/source/smbparse.c b/source/smbparse.c index 0c016c17d9d..a0363c71087 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -400,7 +400,7 @@ char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) RW_SVAL(io, q, rpc->frag_len, 0); q += 2; RW_SVAL(io, q, rpc->auth_len, 0); q += 2; RW_IVAL(io, q, rpc->call_id, 0); q += 4; - RW_SVAL(io, q, rpc->alloc_hint, 0); q += 2; + RW_IVAL(io, q, rpc->alloc_hint, 0); q += 4; RW_CVAL(io, q, rpc->context_id, 0); q++; RW_CVAL(io, q, rpc->reserved, 0); q++; -- cgit From e02aa88e25ae6d4da7953aaff04ff2ae9a656d05 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 12 Oct 1997 19:02:55 +0000 Subject: getting somewhere. ipc.c : removed srvsvc pipe reference: have to do that. pipes.c lsaparse.c smbparse.c : more debugging info. looks a bit like netmon output. --- source/include/byteorder.h | 6 +- source/include/proto.h | 50 ++++---- source/lsaparse.c | 100 +++++++-------- source/smbd/ipc.c | 7 +- source/smbd/pipes.c | 109 ++++++++-------- source/smbparse.c | 300 ++++++++++++++++++++++++++++----------------- 6 files changed, 330 insertions(+), 242 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index e8989ee7e44..c0e38adc2b6 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -215,15 +215,15 @@ it also defines lots of intermediate macros, just ignore those :-) #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ RW_CVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s %04x %s: %02x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); #define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \ RW_SVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s %04x %s: %04x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); #define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \ RW_IVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s %04x %s: %08x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, (unsigned int)*(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); diff --git a/source/include/proto.h b/source/include/proto.h index 1ac4132807e..72b15173ecc 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -818,32 +818,32 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24); /*The following definitions come from smbparse.c */ -char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align); -char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align); -char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align); -char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align); -char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align); -char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align); -char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align); -char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align); -char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align); -char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align); -char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align); -char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align); -char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align); -char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align); -char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align); -char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align); -char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align); -char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align); -char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align); +char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align, int depth); +char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align, int depth); +char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int depth); +char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int depth); +char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align, int depth); +char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align, int depth); +char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int depth); +char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, int depth); +char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, int depth); +char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align, int depth); +char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int depth); +char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int depth); +char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align, int depth); +char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align, int depth); +char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align, int depth); +char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align, int depth); +char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align, int depth); +char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align, int depth); +char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align, int depth); char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, int depth); -char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); -char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); -char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align); -char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align); -char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align); -char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align); +char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth); +char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth); +char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, int depth); +char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align, int depth); +char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align, int depth); +char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align, int depth); /*The following definitions come from smbpass.c */ diff --git a/source/lsaparse.c b/source/lsaparse.c index ee73dd9a056..34f4cb4048f 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -31,7 +31,7 @@ char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int a { if (r_p == NULL) return NULL; - DEBUG(5,("%slsa_io_r_open_pol\n", tab_depth(depth))); + DEBUG(5,("%s%04x lsa_io_r_open_pol\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align, depth); @@ -78,12 +78,12 @@ char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int al { case 3: { - q = smb_io_dom_query_3(io, &(r_q->dom.id3), q, base, align); + q = smb_io_dom_query_3(io, &(r_q->dom.id3), q, base, align, depth); break; } case 5: { - q = smb_io_dom_query_5(io, &(r_q->dom.id3), q, base, align); + q = smb_io_dom_query_5(io, &(r_q->dom.id3), q, base, align, depth); break; } default: @@ -128,7 +128,7 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, for (i = 0; i < q_s->num_entries; i++) { - q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align); /* domain SIDs to be looked up. */ + q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align, depth); /* domain SIDs to be looked up. */ } DBG_RW_PCVAL("undoc", depth, base, io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ @@ -150,7 +150,7 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, q = align_offset(q, base, align); - q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align); /* domain reference info */ + q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align, depth); /* domain reference info */ DBG_RW_IVAL("num_entries", depth, base, io, q, r_s->num_entries); q += 4; DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_s->undoc_buffer); q += 4; @@ -158,7 +158,7 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, for (i = 0; i < r_s->num_entries2; i++) { - q = smb_io_dom_sid2(io, &(r_s->dom_sid[i]), q, base, align); /* domain SIDs being looked up */ + q = smb_io_dom_sid2(io, &(r_s->dom_sid[i]), q, base, align, depth); /* domain SIDs being looked up */ } DBG_RW_IVAL("num_entries3", depth, base, io, q, r_s->num_entries3); q += 4; @@ -191,7 +191,7 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, for (i = 0; i < q_r->num_entries; i++) { - q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, 0); /* names to be looked up */ + q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, align, depth); /* names to be looked up */ } DBG_RW_PCVAL("undoc", depth, base, io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ @@ -213,7 +213,7 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, q = align_offset(q, base, align); - q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align); /* domain reference info */ + q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align, depth); /* domain reference info */ DBG_RW_IVAL("num_entries", depth, base, io, q, r_r->num_entries); q += 4; DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_r->undoc_buffer); q += 4; @@ -221,7 +221,7 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, for (i = 0; i < r_r->num_entries2; i++) { - q = smb_io_dom_rid2(io, &(r_r->dom_rid[i]), q, base, align); /* domain RIDs being looked up */ + q = smb_io_dom_rid2(io, &(r_r->dom_rid[i]), q, base, align, depth); /* domain RIDs being looked up */ } DBG_RW_IVAL("num_entries3", depth, base, io, q, r_r->num_entries3); q += 4; @@ -243,9 +243,11 @@ char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int a q = align_offset(q, base, align); - q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align); /* logon server unicode string */ - q = smb_io_unistr2(io, &(q_c->uni_logon_clnt), q, base, align); /* logon client unicode string */ - q = smb_io_chal(io, &(q_c->clnt_chal), q, base, align); /* client challenge */ + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, q_c->undoc_buffer); q += 4; + + q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align, depth); /* logon server unicode string */ + q = smb_io_unistr2(io, &(q_c->uni_logon_clnt), q, base, align, depth); /* logon client unicode string */ + q = smb_io_chal(io, &(q_c->clnt_chal), q, base, align, depth); /* client challenge */ return q; } @@ -262,7 +264,7 @@ char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int a q = align_offset(q, base, align); - q = smb_io_chal(io, &(r_c->srv_chal), q, base, align); /* server challenge */ + q = smb_io_chal(io, &(r_c->srv_chal), q, base, align, depth); /* server challenge */ DBG_RW_IVAL("status", depth, base, io, q, r_c->status); q += 4; @@ -282,9 +284,9 @@ char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align q = align_offset(q, base, align); - q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align); /* client identification info */ - q = smb_io_chal (io, &(q_a->clnt_chal), q, base, align); /* client-calculated credentials */ - q = smb_io_neg_flags(io, &(q_a->clnt_flgs), q, base, align); + q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align, depth); /* client identification info */ + q = smb_io_chal (io, &(q_a->clnt_chal), q, base, align, depth); /* client-calculated credentials */ + q = smb_io_neg_flags(io, &(q_a->clnt_flgs), q, base, align, depth); return q; } @@ -301,8 +303,8 @@ char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align q = align_offset(q, base, align); - q = smb_io_chal (io, &(r_a->srv_chal), q, base, align); /* server challenge */ - q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align); + q = smb_io_chal (io, &(r_a->srv_chal), q, base, align, depth); /* server challenge */ + q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align, depth); DBG_RW_IVAL("status", depth, base, io, q, r_a->status); q += 4; @@ -322,7 +324,7 @@ char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int q = align_offset(q, base, align); - q = smb_io_clnt_info(io, &(q_s->clnt_id), q, base, align); /* client identification/authentication info */ + q = smb_io_clnt_info(io, &(q_s->clnt_id), q, base, align, depth); /* client identification/authentication info */ DBG_RW_PCVAL("pwd", depth, base, io, q, q_s->pwd, 16); q += 16; /* new password - undocumented */ return q; @@ -340,7 +342,7 @@ char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int q = align_offset(q, base, align); - q = smb_io_cred(io, &(r_s->srv_cred), q, base, align); /* server challenge */ + q = smb_io_cred(io, &(r_s->srv_cred), q, base, align, depth); /* server challenge */ DBG_RW_IVAL("status", depth, base, io, q, r_s->status); q += 4; @@ -365,19 +367,19 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali DBG_RW_IVAL("", depth, base, io, q, usr->undoc_buffer); q += 4; - q = smb_io_time(io, &(usr->logon_time) , q, base, align); /* logon time */ - q = smb_io_time(io, &(usr->logoff_time) , q, base, align); /* logoff time */ - q = smb_io_time(io, &(usr->kickoff_time) , q, base, align); /* kickoff time */ - q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align); /* password last set time */ - q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align); /* password can change time */ - q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align); /* password must change time */ + q = smb_io_time(io, &(usr->logon_time) , q, base, align, depth); /* logon time */ + q = smb_io_time(io, &(usr->logoff_time) , q, base, align, depth); /* logoff time */ + q = smb_io_time(io, &(usr->kickoff_time) , q, base, align, depth); /* kickoff time */ + q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align, depth); /* password last set time */ + q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align, depth); /* password can change time */ + q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align, depth); /* password must change time */ - q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align); /* username unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align); /* user's full name unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align); /* logon script unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align); /* profile path unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align); /* home directory unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align); /* home directory drive unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align, depth); /* username unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align, depth); /* user's full name unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align, depth); /* logon script unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align, depth); /* profile path unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align, depth); /* home directory unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align, depth); /* home directory drive unicode string header */ DBG_RW_SVAL("logon_count", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ DBG_RW_SVAL("bad_pw_count", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ @@ -390,8 +392,8 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali DBG_RW_PCVAL("", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ - q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align); /* logon server unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align); /* logon domain unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align, depth); /* logon server unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align, depth); /* logon domain unicode string header */ DBG_RW_IVAL("buffer_dom_id", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ DBG_RW_PCVAL("padding", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ @@ -399,27 +401,27 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali DBG_RW_IVAL("num_other_sids", depth, base, io, q, usr->num_other_sids); q += 4; /* 0 - num_sids */ DBG_RW_IVAL("buffer_other_sids", depth, base, io, q, usr->buffer_other_sids); q += 4; /* NULL - undocumented pointer to SIDs. */ - q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align); /* username unicode string */ - q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align); /* user's full name unicode string */ - q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align); /* logon script unicode string */ - q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align); /* profile path unicode string */ - q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align); /* home directory unicode string */ - q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align); /* home directory drive unicode string */ + q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align, depth); /* username unicode string */ + q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align, depth); /* user's full name unicode string */ + q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align, depth); /* logon script unicode string */ + q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align, depth); /* profile path unicode string */ + q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align, depth); /* home directory unicode string */ + q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align, depth); /* home directory drive unicode string */ DBG_RW_IVAL("num_groups2", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ for (i = 0; i < usr->num_groups2; i++) { - q = smb_io_gid(io, &(usr->gids[i]), q, base, align); /* group info */ + q = smb_io_gid(io, &(usr->gids[i]), q, base, align, depth); /* group info */ } - q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align); /* logon server unicode string */ - q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align); /* logon domain unicode string */ + q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align, depth); /* logon server unicode string */ + q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align, depth); /* logon domain unicode string */ - q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align); /* domain SID */ + q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align, depth); /* domain SID */ for (i = 0; i < usr->num_other_sids; i++) { - q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align); /* other domain SIDs */ + q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align, depth); /* other domain SIDs */ } return q; @@ -437,7 +439,7 @@ char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int q = align_offset(q, base, align); - q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ + q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align, depth); /* domain SID */ return q; } @@ -455,7 +457,7 @@ char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int q = align_offset(q, base, align); DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ - q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ + q = smb_io_cred(io, &(r_l->srv_creds), q, base, align, depth); /* server credentials. server time stamp appears to be ignored. */ DBG_RW_IVAL("buffer_user", depth, base, io, q, r_l->buffer_user); q += 4; if (r_l->buffer_user != 0) @@ -482,7 +484,7 @@ char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, i q = align_offset(q, base, align); - q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ + q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align, depth); /* domain SID */ return q; } @@ -500,7 +502,7 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i q = align_offset(q, base, align); DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ - q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ + q = smb_io_cred(io, &(r_l->srv_creds), q, base, align, depth); /* server credentials. server time stamp appears to be ignored. */ DBG_RW_IVAL("status", depth, base, io, q, r_l->status); q += 4; diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index b314d416792..468d34e157f 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2762,13 +2762,14 @@ struct BOOL (*fn) (); } api_fd_commands [] = { - { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, #ifdef NTDOMAIN + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, - { "SetNmdPpHndState", "NETLOGON", 1, api_netlogrpcTNP }, #else - { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, #endif { NULL, NULL, -1, (BOOL (*)())api_Unsupported } }; diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 4f1d0152168..eb8215b7a33 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -53,11 +53,10 @@ a packet to ensure chaining works correctly */ char * known_pipes [] = { + "lsarpc", #if NTDOMAIN "NETLOGON", - "srvsvc", #endif - "lsarpc", NULL }; @@ -483,7 +482,7 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->minor = 0; /* minor version 0 */ hdr->pkt_type = 2; /* RPC response packet */ hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 0x10; /* packed data representation */ + hdr->pack_type = 1; /* packed data representation */ hdr->frag_len = data_len; /* fragment length, fill in later */ hdr->auth_len = 0; /* authentication length */ hdr->call_id = call_id; /* call identifier - match incoming RPC */ @@ -495,32 +494,24 @@ static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) static int make_rpc_reply(char *inbuf, char *q, int data_len) { - uint32 callid = IVAL(inbuf, 12); + uint32 callid = RIVAL(inbuf, 12); RPC_HDR hdr; - DEBUG(5,("make_rpc_reply. callid: %x\n", callid)); - create_rpc_reply(&hdr, callid, data_len); - return PTR_DIFF(smb_io_rpc_hdr(False, &hdr, q, q, 4), q); + return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q; } static int lsa_reply_open_policy(char *q, char *base) { int i; + char *start = q; LSA_R_OPEN_POL r_o; - static char handle[20] = - { 0x00, 0x00, 0x00, 0x00, - 0x2f, 0x79, 0x0a, 0x81, - 0xd5, 0x17, 0xd1, 0x11, - 0x80, 0xaf, 0x96, 0xcd, - 0x50, 0xf8, 0xbc, 0x6c - }; /* set up the LSA QUERY INFO response */ /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ for (i = 0; i < POL_HND_SIZE; i++) { - r_o.pol.data[i] = handle[i]; + r_o.pol.data[i] = i; } r_o.status = 0x0; @@ -528,7 +519,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -602,6 +593,7 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { + char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -617,7 +609,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -701,6 +693,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { + char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -712,7 +705,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static int lsa_reply_lookup_rids(char *q, char *base, @@ -720,6 +713,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { + char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -731,7 +725,7 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, @@ -739,11 +733,16 @@ static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, { memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); r_c->status = status; + + DEBUG(5,("make_lsa_r_req_chal srv_chal: %lx %lx\n", + *(uint32*)(&((r_c->srv_chal.data[0]))), + *(uint32*)(&((r_c->srv_chal.data[4]))) )); } static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { + char *start = q; LSA_R_REQ_CHAL r_c; /* set up the LSA REQUEST CHALLENGE response */ @@ -754,7 +753,7 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -768,6 +767,7 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { + char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -778,7 +778,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -791,6 +791,7 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { + char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -800,7 +801,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -919,6 +920,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { + char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -934,7 +936,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } @@ -942,6 +944,7 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { + char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -954,23 +957,31 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return PTR_DIFF(q, base); + return q - start; } static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ - /* construct a 20 byte policy handle. return length*/ - *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); + /* return a 20 byte policy handle */ + reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } -static int api_lsa_query_info( char *param, char *data, +static void api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; @@ -982,13 +993,19 @@ static int api_lsa_query_info( char *param, char *data, pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - return lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, + reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, dom_name, dom_sid); + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1008,15 +1025,21 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, + reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { + int reply_len; + int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1037,10 +1060,14 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, + reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ + + /* construct header, now that we know the reply length */ + make_rpc_reply(data, *rdata, reply_len); + *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1065,8 +1092,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1075,8 +1100,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1138,8 +1161,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1147,8 +1168,6 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; } @@ -1642,16 +1661,10 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - uint16 opnum; - char pkttype; - user_struct *vuser; - - DEBUG(5,("api_netlogrpcTNP data:%x\n", data)); - - if (data == NULL) return False; + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); - opnum = SVAL(data,22); - pkttype = CVAL(data, 2); + user_struct *vuser; if (pkttype == 0x0b) /* RPC BIND */ { @@ -1660,7 +1673,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, return True; } - DEBUG(4,("netlogon TransactNamedPipe op %x\n", opnum)); + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); if ((vuser = get_valid_user_struct(uid)) == NULL) return False; diff --git a/source/smbparse.c b/source/smbparse.c index a0363c71087..d7fbf53020e 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -27,13 +27,16 @@ extern int DEBUGLEVEL; /******************************************************************* reads or writes a UTIME type. ********************************************************************/ -char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align) +char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align, int depth) { if (t == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_utime\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL (io, q, t->time, 0); q += 4; + DBG_RW_IVAL ("time", depth, base, io, q, t->time); q += 4; return q; } @@ -41,14 +44,17 @@ char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align) /******************************************************************* reads or writes an NTTIME structure. ********************************************************************/ -char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align) +char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align, int depth) { if (nttime == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_time\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, nttime->low , 0); q += 4; /* low part */ - RW_IVAL(io, q, nttime->high, 0); q += 4; /* high part */ + DBG_RW_IVAL("low", depth, base, io, q, nttime->low ); q += 4; /* low part */ + DBG_RW_IVAL("high", depth, base, io, q, nttime->high); q += 4; /* high part */ return q; } @@ -56,26 +62,31 @@ char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_SID structure. ********************************************************************/ -char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) +char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int depth) { int i; if (sid == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_dom_sid\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_CVAL(io, q, sid->sid_no, 0); q++; - RW_CVAL(io, q, sid->num_auths, 0); q++; + DBG_RW_CVAL("sid_no", depth, base, io, q, sid->sid_no); q++; + DBG_RW_CVAL("num_auths", depth, base, io, q, sid->num_auths); q++; for (i = 0; i < 6; i++) { - RW_CVAL(io, q, sid->id_auth[i], 0); q++; + fstring tmp; + sprintf(tmp, "id_auth[%d] ", i); + DBG_RW_CVAL(tmp, depth, base, io, q, sid->id_auth[i]); q++; } /* oops! XXXX should really issue a warning here... */ if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; - RW_PSVAL(io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; + DBG_RW_PSVAL("num_auths", depth, base, io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; return q; } @@ -83,18 +94,21 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) /******************************************************************* reads or writes a UNIHDR structure. ********************************************************************/ -char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align) +char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int depth) { if (hdr == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_unihdr\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + /* should be value 4, so enforce it. */ hdr->undoc = 4; q = align_offset(q, base, align); - RW_IVAL(io, q, hdr->uni_max_len, 0); q += 4; - RW_IVAL(io, q, hdr->uni_str_len, 0); q += 4; - RW_IVAL(io, q, hdr->undoc , 0); q += 4; + DBG_RW_IVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 4; + DBG_RW_IVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 4; + DBG_RW_IVAL("undoc", depth, base, io, q, hdr->undoc ); q += 4; return q; } @@ -102,14 +116,17 @@ char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align) /******************************************************************* reads or writes a UNIHDR2 structure. ********************************************************************/ -char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align) +char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align, int depth) { if (hdr2 == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_unihdr2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - q = smb_io_unihdr(io, &(hdr2->unihdr), q, base, align); - RW_IVAL(io, q, hdr2->undoc_buffer, 0); q += 4; + q = smb_io_unihdr(io, &(hdr2->unihdr), q, base, align, depth); + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, hdr2->undoc_buffer); q += 4; return q; } @@ -118,10 +135,13 @@ char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align) reads or writes a UNISTR structure. XXXX NOTE: UNISTR structures NEED to be null-terminated. ********************************************************************/ -char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align) +char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align, int depth) { if (uni == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_unistr\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); if (io) @@ -143,18 +163,21 @@ XXXX NOTE: UNISTR2 structures need NOT be null-terminated. the uni_str_len member tells you how long the string is; the uni_max_len member tells you how large the buffer is. ********************************************************************/ -char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align) +char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int depth) { if (uni2 == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_unistr2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); /* should be value 0, so enforce it. */ uni2->undoc = 0; - RW_IVAL(io, q, uni2->uni_max_len, 0); q += 4; - RW_IVAL(io, q, uni2->undoc , 0); q += 4; - RW_IVAL(io, q, uni2->uni_str_len, 0); q += 4; + DBG_RW_IVAL("uni_max_len", depth, base, io, q, uni2->uni_max_len); q += 4; + DBG_RW_IVAL("undoc", depth, base, io, q, uni2->undoc ); q += 4; + DBG_RW_IVAL("uni_str_len", depth, base, io, q, uni2->uni_str_len); q += 4; /* oops! XXXX maybe issue a warning that this is happening... */ if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN; @@ -162,7 +185,7 @@ char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align) /* buffer advanced by indicated length of string NOT by searching for null-termination */ - RW_PSVAL(io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; + DBG_RW_PSVAL("", depth, base, io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; return q; } @@ -170,10 +193,13 @@ char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_SID2 structure. ********************************************************************/ -char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align) +char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, int depth) { if (sid2 == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_dom_sid2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); /* should be value 5, so enforce it */ @@ -182,11 +208,11 @@ char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align) /* should be value 0, so enforce it */ sid2->undoc = 0; - RW_IVAL(io, q, sid2->type , 0); q += 4; - RW_IVAL(io, q, sid2->undoc, 0); q += 4; + DBG_RW_IVAL("type", depth, base, io, q, sid2->type ); q += 4; + DBG_RW_IVAL("undoc", depth, base, io, q, sid2->undoc); q += 4; - q = smb_io_unihdr2(io, &(sid2->hdr), q, base, align); - q = smb_io_unistr (io, &(sid2->str), q, base, align); + q = smb_io_unihdr2(io, &(sid2->hdr), q, base, align, depth); + q = smb_io_unistr (io, &(sid2->str), q, base, align, depth); return q; } @@ -194,10 +220,13 @@ char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_RID2 structure. ********************************************************************/ -char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align) +char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, int depth) { if (rid2 == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_dom_rid2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); /* should be value 5, so enforce it */ @@ -206,10 +235,10 @@ char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align) /* should be value 5, so enforce it */ rid2->undoc = 5; - RW_IVAL(io, q, rid2->type, 0); q += 4; - RW_IVAL(io, q, rid2->undoc , 0); q += 4; - RW_IVAL(io, q, rid2->rid , 0); q += 4; - RW_IVAL(io, q, rid2->rid_idx , 0); q += 4; + DBG_RW_IVAL("type", depth, base, io, q, rid2->type); q += 4; + DBG_RW_IVAL("undoc", depth, base, io, q, rid2->undoc ); q += 4; + DBG_RW_IVAL("rid", depth, base, io, q, rid2->rid ); q += 4; + DBG_RW_IVAL("rid_idx", depth, base, io, q, rid2->rid_idx ); q += 4; return q; } @@ -217,21 +246,24 @@ char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_LOG_INFO structure. ********************************************************************/ -char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align) +char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align, int depth) { if (log == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_log_info\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, log->undoc_buffer, 0); q += 4; + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, log->undoc_buffer); q += 4; - q = smb_io_unistr2(io, &(log->uni_logon_srv), q, base, align); - q = smb_io_unistr2(io, &(log->uni_acct_name), q, base, align); + q = smb_io_unistr2(io, &(log->uni_logon_srv), q, base, align, depth); + q = smb_io_unistr2(io, &(log->uni_acct_name), q, base, align, depth); - RW_SVAL(io, q, log->sec_chan, 0); q += 2; + DBG_RW_SVAL("sec_chan", depth, base, io, q, log->sec_chan); q += 2; /* XXXX no alignment required between sec_chan and uni_comp_name */ - q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, 0); + q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, 0, depth); return q; } @@ -239,13 +271,16 @@ char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align /******************************************************************* reads or writes a DOM_CHAL structure. ********************************************************************/ -char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align) +char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int depth) { if (chal == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_chal\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_PCVAL(io, q, chal->data, 8); q += 8; + DBG_RW_PCVAL("data", depth, base, io, q, chal->data, 8); q += 8; return q; } @@ -253,14 +288,17 @@ char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_CRED structure. ********************************************************************/ -char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align) +char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int depth) { if (cred == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_cred\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - q = smb_io_chal (io, &(cred->challenge), q, base, align); - q = smb_io_utime(io, &(cred->timestamp), q, base, align); + q = smb_io_chal (io, &(cred->challenge), q, base, align, depth); + q = smb_io_utime(io, &(cred->timestamp), q, base, align, depth); return q; } @@ -268,14 +306,17 @@ char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_CLNT_INFO structure. ********************************************************************/ -char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align) +char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align, int depth) { if (clnt == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_clnt_info\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - q = smb_io_log_info(io, &(clnt->login), q, base, align); - q = smb_io_cred (io, &(clnt->cred ), q, base, align); + q = smb_io_log_info(io, &(clnt->login), q, base, align, depth); + q = smb_io_cred (io, &(clnt->cred ), q, base, align, depth); return q; } @@ -283,14 +324,17 @@ char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int al /******************************************************************* reads or writes a DOM_LOGON_ID structure. ********************************************************************/ -char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align) +char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align, int depth) { if (log == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_logon_id\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, log->low , 0); q += 4; - RW_IVAL(io, q, log->high, 0); q += 4; + DBG_RW_IVAL("low", depth, base, io, q, log->low ); q += 4; + DBG_RW_IVAL("high", depth, base, io, q, log->high); q += 4; return q; } @@ -298,13 +342,16 @@ char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align /******************************************************************* reads or writes an ARC4_OWF structure. ********************************************************************/ -char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align) +char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align, int depth) { if (hash == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_arc4_owf\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_PCVAL(io, q, hash->data, 16); q += 16; + DBG_RW_PCVAL("data", depth, base, io, q, hash->data, 16); q += 16; return q; } @@ -312,26 +359,29 @@ char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align) /******************************************************************* reads or writes an DOM_ID_INFO_1 structure. ********************************************************************/ -char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align) +char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align, int depth) { if (id == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_id_info1\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align); + q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align, depth); - RW_IVAL(io, q, id->param, 0); q += 4; - q = smb_io_logon_id(io, &(id->logon_id), q, base, align); + DBG_RW_IVAL("param", depth, base, io, q, id->param); q += 4; + q = smb_io_logon_id(io, &(id->logon_id), q, base, align, depth); - q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align); - q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align); + q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align, depth); + q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align, depth); - q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align); - q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align); + q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align, depth); + q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align, depth); - q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align); - q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align); - q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align); + q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align, depth); + q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align, depth); + q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align, depth); return q; } @@ -339,23 +389,26 @@ char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align /******************************************************************* reads or writes a DOM_SAM_INFO structure. ********************************************************************/ -char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align) +char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align, int depth) { if (sam == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_sam_info\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - q = smb_io_clnt_info(io, &(sam->client ), q, base, align); - q = smb_io_cred (io, &(sam->rtn_cred), q, base, align); + q = smb_io_clnt_info(io, &(sam->client ), q, base, align, depth); + q = smb_io_cred (io, &(sam->rtn_cred), q, base, align, depth); - RW_IVAL(io, q, sam->logon_level, 0); q += 4; - RW_SVAL(io, q, sam->auth_level , 0); q += 4; + DBG_RW_IVAL("logon_level", depth, base, io, q, sam->logon_level); q += 4; + DBG_RW_SVAL("auth_level", depth, base, io, q, sam->auth_level ); q += 4; switch (sam->auth_level) { case 1: { - q = smb_io_id_info1(io, &(sam->auth.id1), q, base, align); + q = smb_io_id_info1(io, &(sam->auth.id1), q, base, align, depth); break; } default: @@ -370,14 +423,17 @@ char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align /******************************************************************* reads or writes a DOM_GID structure. ********************************************************************/ -char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align) +char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align, int depth) { if (gid == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_gid\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, gid->gid , 0); q += 4; - RW_IVAL(io, q, gid->attr, 0); q += 4; + DBG_RW_IVAL("gid", depth, base, io, q, gid->gid ); q += 4; + DBG_RW_IVAL("attr", depth, base, io, q, gid->attr); q += 4; return q; } @@ -385,24 +441,27 @@ char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align) /******************************************************************* reads or writes an RPC_HDR structure. ********************************************************************/ -char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) +char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align, int depth) { if (rpc == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_rpc_hdr\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + /* reserved should be zero: enforce it */ rpc->reserved = 0; - RW_CVAL(io, q, rpc->major, 0); q++; - RW_CVAL(io, q, rpc->minor, 0); q++; - RW_CVAL(io, q, rpc->pkt_type, 0); q++; - RW_CVAL(io, q, rpc->frag, 0); q++; - RW_IVAL(io, q, rpc->pack_type, 0); q += 4; - RW_SVAL(io, q, rpc->frag_len, 0); q += 2; - RW_SVAL(io, q, rpc->auth_len, 0); q += 2; - RW_IVAL(io, q, rpc->call_id, 0); q += 4; - RW_IVAL(io, q, rpc->alloc_hint, 0); q += 4; - RW_CVAL(io, q, rpc->context_id, 0); q++; - RW_CVAL(io, q, rpc->reserved, 0); q++; + DBG_RW_CVAL("major", depth, base, io, q, rpc->major); q++; + DBG_RW_CVAL("minor", depth, base, io, q, rpc->minor); q++; + DBG_RW_CVAL("pkt_type", depth, base, io, q, rpc->pkt_type); q++; + DBG_RW_CVAL("frag", depth, base, io, q, rpc->frag); q++; + DBG_RW_IVAL("pack_type", depth, base, io, q, rpc->pack_type); q += 4; + DBG_RW_SVAL("frag_len", depth, base, io, q, rpc->frag_len); q += 2; + DBG_RW_SVAL("auth_len", depth, base, io, q, rpc->auth_len); q += 2; + DBG_RW_IVAL("call_id", depth, base, io, q, rpc->call_id); q += 4; + DBG_RW_IVAL("alloc_hint", depth, base, io, q, rpc->alloc_hint); q += 4; + DBG_RW_CVAL("context_id", depth, base, io, q, rpc->context_id); q++; + DBG_RW_CVAL("reserved", depth, base, io, q, rpc->reserved); q++; return q; } @@ -414,7 +473,7 @@ char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, { if (pol == NULL) return NULL; - DEBUG(5,("%ssmb_io_pol_hnd\n", tab_depth(depth))); + DEBUG(5,("%s%04x smb_io_pol_hnd\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; q = align_offset(q, base, align); @@ -427,43 +486,46 @@ char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, /******************************************************************* reads or writes a dom query structure. ********************************************************************/ -char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) +char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth) { - return smb_io_dom_query(io, d_q, q, base, align); + return smb_io_dom_query(io, d_q, q, base, align, depth); } /******************************************************************* reads or writes a dom query structure. ********************************************************************/ -char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) +char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth) { - return smb_io_dom_query(io, d_q, q, base, align); + return smb_io_dom_query(io, d_q, q, base, align, depth); } /******************************************************************* reads or writes a dom query structure. ********************************************************************/ -char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) +char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, int depth) { if (d_q == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_dom_query\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_SVAL(io, q, d_q->uni_dom_max_len, 0); q += 2; /* domain name string length * 2 */ - RW_SVAL(io, q, d_q->padding , 0); q += 2; /* 2 padding bytes */ - RW_SVAL(io, q, d_q->uni_dom_str_len, 0); q += 2; /* domain name string length * 2 */ + DBG_RW_SVAL("uni_dom_max_len", depth, base, io, q, d_q->uni_dom_max_len); q += 2; /* domain name string length * 2 */ + DBG_RW_SVAL("padding", depth, base, io, q, d_q->padding ); q += 2; /* 2 padding bytes */ + DBG_RW_SVAL("uni_dom_str_len", depth, base, io, q, d_q->uni_dom_str_len); q += 2; /* domain name string length * 2 */ - RW_IVAL(io, q, d_q->buffer_dom_name, 0); q += 4; /* undocumented domain name string buffer pointer */ - RW_IVAL(io, q, d_q->buffer_dom_sid , 0); q += 4; /* undocumented domain SID string buffer pointer */ + DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, d_q->buffer_dom_name); q += 4; /* undocumented domain name string buffer pointer */ + DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, d_q->buffer_dom_sid ); q += 4; /* undocumented domain SID string buffer pointer */ if (d_q->buffer_dom_name != 0) { - q = smb_io_unistr2(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ + q = smb_io_unistr2(io, &(d_q->uni_domain_name), q, base, align, depth); /* domain name (unicode string) */ } if (d_q->buffer_dom_sid != 0) { - q = smb_io_dom_sid(io, &(d_q->dom_sid), q, base, align); /* domain SID */ + q = smb_io_dom_sid(io, &(d_q->dom_sid), q, base, align, depth); /* domain SID */ } return q; @@ -472,32 +534,35 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_R_REF structure. ********************************************************************/ -char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align) +char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align, int depth) { int i; + DEBUG(5,("%s%04x smb_io_dom_r_ref\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + if (r_r == NULL) return NULL; q = align_offset(q, base, align); - RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; /* undocumented buffer pointer. */ - RW_IVAL(io, q, r_r->num_ref_doms_1, 0); q += 4; /* num referenced domains? */ - RW_IVAL(io, q, r_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer. */ - RW_IVAL(io, q, r_r->max_entries, 0); q += 4; /* 32 - max number of entries */ - RW_IVAL(io, q, r_r->num_ref_doms_2, 0); q += 4; /* 4 - num referenced domains? */ + DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_r->undoc_buffer); q += 4; /* undocumented buffer pointer. */ + DBG_RW_IVAL("num_ref_doms_1", depth, base, io, q, r_r->num_ref_doms_1); q += 4; /* num referenced domains? */ + DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, r_r->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer. */ + DBG_RW_IVAL("max_entries", depth, base, io, q, r_r->max_entries); q += 4; /* 32 - max number of entries */ + DBG_RW_IVAL("num_ref_doms_2", depth, base, io, q, r_r->num_ref_doms_2); q += 4; /* 4 - num referenced domains? */ - q = smb_io_unihdr2(io, &(r_r->hdr_dom_name), q, base, align); /* domain name unicode string header */ + q = smb_io_unihdr2(io, &(r_r->hdr_dom_name), q, base, align, depth); /* domain name unicode string header */ for (i = 0; i < r_r->num_ref_doms_1-1; i++) { - q = smb_io_unihdr2(io, &(r_r->hdr_ref_dom[i]), q, base, align); + q = smb_io_unihdr2(io, &(r_r->hdr_ref_dom[i]), q, base, align, depth); } - q = smb_io_unistr(io, &(r_r->uni_dom_name), q, base, align); /* domain name unicode string */ + q = smb_io_unistr(io, &(r_r->uni_dom_name), q, base, align, depth); /* domain name unicode string */ for (i = 0; i < r_r->num_ref_doms_2; i++) { - q = smb_io_dom_sid(io, &(r_r->ref_dom[i]), q, base, align); /* referenced domain SIDs */ + q = smb_io_dom_sid(io, &(r_r->ref_dom[i]), q, base, align, depth); /* referenced domain SIDs */ } return q; } @@ -505,18 +570,21 @@ char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align) /******************************************************************* reads or writes a DOM_NAME structure. ********************************************************************/ -char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align) +char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align, int depth) { if (name == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_dom_name\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, name->uni_str_len, 0); q += 4; + DBG_RW_IVAL("uni_str_len", depth, base, io, q, name->uni_str_len); q += 4; /* don't know if len is specified by uni_str_len member... */ /* assume unicode string is unicode-null-terminated, instead */ - q = smb_io_unistr(io, &(name->str), q, base, align); + q = smb_io_unistr(io, &(name->str), q, base, align, depth); return q; } @@ -525,13 +593,16 @@ char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align) /******************************************************************* reads or writes a structure. ********************************************************************/ -char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align) +char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align, int depth) { if (neg == NULL) return NULL; + DEBUG(5,("%s%04x smb_io_neg_flags\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + q = align_offset(q, base, align); - RW_IVAL(io, q, neg->neg_flags, 0); q += 4; + DBG_RW_IVAL("neg_flags", depth, base, io, q, neg->neg_flags); q += 4; return q; } @@ -541,14 +612,15 @@ char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align) /******************************************************************* reads or writes a structure. ********************************************************************/ - char* smb_io_(BOOL io, *, char *q, char *base, int align) + char* smb_io_(BOOL io, *, char *q, char *base, int align, int depth) { if (== NULL) return NULL; q = align_offset(q, base, align); - RW_IVAL(io, q, , 0); q += 4; + DBG_RW_IVAL("", depth, base, io, q, ); q += 4; return q; } #endif + -- cgit From 849875f85196c0d3461b9466785c8f00ade0ec1f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 12 Oct 1997 23:51:46 +0000 Subject: updated the "comment =" entry a bit --- docs/manpages/smb.conf.5 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 5c4ce3375fe..740c0921919 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -865,9 +865,11 @@ See also : "valid chars". client code page = 437 .SS comment (S) -This is a text field that is seen when a client does a net view to -list what shares are available. It will also be used when browsing is -fully supported. +This is a text field that is seen next to a share when a client does a +net view to list what shares are available. + +If you want to set the string that is displayed next to the machine +name then see the server string command. .B Default: No comment string -- cgit From 60bb523c8a67065d0ede732e1c153f37a8a865b6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 13 Oct 1997 00:03:37 +0000 Subject: updated the "comment =" entry a bit updated the fake oplocks entry a bit --- docs/manpages/smb.conf.5 | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index bb43941439a..9b8dfd3f280 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -871,9 +871,11 @@ See also : "valid chars". client code page = 437 .SS comment (S) -This is a text field that is seen when a client does a net view to -list what shares are available. It will also be used when browsing is -fully supported. +This is a text field that is seen next to a share when a client does a +net view to list what shares are available. + +If you want to set the string that is displayed next to the machine +name then see the server string command. .B Default: No comment string @@ -1238,12 +1240,8 @@ only one accessing the file and it will aggressively cache file data. With some oplock types the client may even cache file open/close operations. This can give enormous performance benefits. -Samba does not support opportunistic locks because they are very -difficult to do under Unix. Samba can fake them, however, by granting -a oplock whenever a client asks for one. This is controlled using the -smb.conf option "fake oplocks". If you set "fake oplocks = yes" then -you are telling the client that it may aggressively cache the file -data. +When you set "fake oplocks = yes" Samba will always grant oplock +requests no matter how many clients are using the file. By enabling this option on all read-only shares or shares that you know will only be accessed from one client at a time you will see a big @@ -1252,6 +1250,9 @@ on shares where multiple clients may be accessing the files read-write at the same time you can get data corruption. Use this option carefully! +It is generally much better to use the real oplock support except for +physically read-only media such as CDROMs. + This option is disabled by default. .SS follow symlinks (S) -- cgit From ba28678e3f673cd10d936f59ff0df6a852aca793 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 11:15:46 +0000 Subject: align_offset() adjusted pointer to wrong location. oops. --- source/lib/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/lib/util.c b/source/lib/util.c index a68b8c2e6c1..0a8540b48b4 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4383,9 +4383,10 @@ will work for offsets of 0, 2 and 4... ********************************************************************/ char *align_offset(char *q, char *base, int align_offset_len) { - if (align_offset_len != 0 && ((q - base) & (align_offset_len-1))) + int mod = ((q - base) & (align_offset_len-1)); + if (align_offset_len != 0 && mod != 0) { - q += align_offset_len - ((q - base) & (align_offset_len)); + q += align_offset_len - mod; } return q; } -- cgit From 534b4c6d371eff6fdbcbcf5fafa3b79d3116b544 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Mon, 13 Oct 1997 12:13:11 +0000 Subject: JHT ==> Removed linefeed that caused problems. --- source/smbadduser | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/smbadduser b/source/smbadduser index 789cc927eb1..e4e1b273d14 100755 --- a/source/smbadduser +++ b/source/smbadduser @@ -55,8 +55,7 @@ foreach one ($argv) echo "Adding: $unix to $smbpasswd" eval $passwd | \ awk -F: '$1==USR { \ - printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", -$1, $3, $5, $6, $7) }' USR=$unix >> $smbpasswd + printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) }' USR=$unix >> $smbpasswd if ($unix != $ntid) then echo "Adding: {$unix = $ntid} to $user_map" echo "$unix = $ntid" >> $user_map @@ -71,4 +70,4 @@ foreach one ($new) echo $line echo "ENTER password for $one" smbpasswd $one -end \ No newline at end of file +end -- cgit From 9fdd697d17b68293bb95fd68f44c24f0f5b97f5f Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 12:21:56 +0000 Subject: byteorder.h : debugging output wasn't (still isn't) perfect. credentials.c lsaparse.c smbparse.c : added DEBUG strings. pipes.c : lost some changes, to do with setup of RPC headers. arg. --- source/include/byteorder.h | 4 +- source/libsmb/credentials.c | 16 +- source/lsaparse.c | 58 ++++---- source/smbd/pipes.c | 346 +++++++------------------------------------- source/smbparse.c | 61 ++++---- source/utils/smbpasswd.c | 6 +- 6 files changed, 131 insertions(+), 360 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index c0e38adc2b6..808026f9dbd 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -202,14 +202,14 @@ it also defines lots of intermediate macros, just ignore those :-) RW_PCVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s %04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (inbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_PSVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PSVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s %04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (inbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index eb1039ddb0b..ce7159f7ffa 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -21,7 +21,7 @@ #include "includes.h" - +extern int DEBUGLEVEL; /**************************************************************************** setup the session key. Input: 8 byte challenge block @@ -37,14 +37,24 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, char sum2[8]; char buf[8]; + DEBUG(4,("cred_session_key\n")); + + DEBUG(5,(" clnt_chal: %lx %lx srv_chal: %lx %lx\n", + + IVAL(clnt_chal->data, 0), IVAL(clnt_chal->data, 4), + IVAL(srv_chal->data, 0), IVAL(srv_chal->data, 4))); + sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - smbhash(pass, sum2, buf); - smbhash(pass+9,buf,session_key); + smbhash(pass , sum2, buf); + smbhash(pass+9, buf , session_key); + + DEBUG(5,(" session_key: ")); + dump_data(5, session_key, 16); } diff --git a/source/lsaparse.c b/source/lsaparse.c index 34f4cb4048f..69352466f6b 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -115,14 +115,14 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align, depth); /* policy handle */ - DBG_RW_IVAL("num_entries", depth, base, io, q, q_s->num_entries); q += 4; - DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, q_s->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ - DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, q_s->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer */ + DBG_RW_IVAL("num_entries ", depth, base, io, q, q_s->num_entries); q += 4; + DBG_RW_IVAL("buffer_dom_sid ", depth, base, io, q, q_s->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ + DBG_RW_IVAL("buffer_dom_name ", depth, base, io, q, q_s->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer */ for (i = 0; i < q_s->num_entries; i++) { fstring temp; - sprintf(temp, "buffer_lookup_sids[%d]", i); + sprintf(temp, "buffer_lookup_sids[%d] ", i); DBG_RW_IVAL(temp, depth, base, io, q, q_s->buffer_lookup_sids[i]); q += 4; /* undocumented domain SID pointers to be looked up. */ } @@ -131,7 +131,7 @@ char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align, depth); /* domain SIDs to be looked up. */ } - DBG_RW_PCVAL("undoc", depth, base, io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ + DBG_RW_PCVAL("undoc ", depth, base, io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ return q; } @@ -152,7 +152,7 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align, depth); /* domain reference info */ - DBG_RW_IVAL("num_entries", depth, base, io, q, r_s->num_entries); q += 4; + DBG_RW_IVAL("num_entries ", depth, base, io, q, r_s->num_entries); q += 4; DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_s->undoc_buffer); q += 4; DBG_RW_IVAL("num_entries2", depth, base, io, q, r_s->num_entries2); q += 4; @@ -163,7 +163,7 @@ char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, DBG_RW_IVAL("num_entries3", depth, base, io, q, r_s->num_entries3); q += 4; - DBG_RW_IVAL("status", depth, base, io, q, r_s->status); q += 4; + DBG_RW_IVAL("status ", depth, base, io, q, r_s->status); q += 4; return q; } @@ -184,9 +184,9 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align, depth); /* policy handle */ - DBG_RW_IVAL("num_entries", depth, base, io, q, q_r->num_entries); q += 4; - DBG_RW_IVAL("num_entries2", depth, base, io, q, q_r->num_entries2); q += 4; - DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, q_r->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ + DBG_RW_IVAL("num_entries ", depth, base, io, q, q_r->num_entries); q += 4; + DBG_RW_IVAL("num_entries2 ", depth, base, io, q, q_r->num_entries2); q += 4; + DBG_RW_IVAL("buffer_dom_sid ", depth, base, io, q, q_r->buffer_dom_sid); q += 4; /* undocumented domain SID buffer pointer */ DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, q_r->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer */ for (i = 0; i < q_r->num_entries; i++) @@ -194,7 +194,7 @@ char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, align, depth); /* names to be looked up */ } - DBG_RW_PCVAL("undoc", depth, base, io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ + DBG_RW_PCVAL("undoc ", depth, base, io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ return q; } @@ -215,7 +215,7 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align, depth); /* domain reference info */ - DBG_RW_IVAL("num_entries", depth, base, io, q, r_r->num_entries); q += 4; + DBG_RW_IVAL("num_entries ", depth, base, io, q, r_r->num_entries); q += 4; DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_r->undoc_buffer); q += 4; DBG_RW_IVAL("num_entries2", depth, base, io, q, r_r->num_entries2); q += 4; @@ -226,7 +226,7 @@ char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, DBG_RW_IVAL("num_entries3", depth, base, io, q, r_r->num_entries3); q += 4; - DBG_RW_IVAL("status", depth, base, io, q, r_r->status); q += 4; + DBG_RW_IVAL("status ", depth, base, io, q, r_r->status); q += 4; return q; } @@ -365,7 +365,7 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = align_offset(q, base, align); - DBG_RW_IVAL("", depth, base, io, q, usr->undoc_buffer); q += 4; + DBG_RW_IVAL("undoc_buffer ", depth, base, io, q, usr->undoc_buffer); q += 4; q = smb_io_time(io, &(usr->logon_time) , q, base, align, depth); /* logon time */ q = smb_io_time(io, &(usr->logoff_time) , q, base, align, depth); /* logoff time */ @@ -381,22 +381,22 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align, depth); /* home directory unicode string header */ q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align, depth); /* home directory drive unicode string header */ - DBG_RW_SVAL("logon_count", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ - DBG_RW_SVAL("bad_pw_count", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ + DBG_RW_SVAL("logon_count. ", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ + DBG_RW_SVAL("bad_pw_count ", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ - DBG_RW_IVAL("user_id", depth, base, io, q, usr->user_id ); q += 4; /* User ID */ - DBG_RW_IVAL("group_id", depth, base, io, q, usr->group_id ); q += 4; /* Group ID */ - DBG_RW_IVAL("num_groups", depth, base, io, q, usr->num_groups ); q += 4; /* num groups */ - DBG_RW_IVAL("buffer_groups", depth, base, io, q, usr->buffer_groups); q += 4; /* undocumented buffer pointer to groups. */ - DBG_RW_IVAL("user_flgs", depth, base, io, q, usr->user_flgs ); q += 4; /* user flags */ + DBG_RW_IVAL("user_id ", depth, base, io, q, usr->user_id ); q += 4; /* User ID */ + DBG_RW_IVAL("group_id ", depth, base, io, q, usr->group_id ); q += 4; /* Group ID */ + DBG_RW_IVAL("num_groups ", depth, base, io, q, usr->num_groups ); q += 4; /* num groups */ + DBG_RW_IVAL("buffer_groups ", depth, base, io, q, usr->buffer_groups); q += 4; /* undocumented buffer pointer to groups. */ + DBG_RW_IVAL("user_flgs ", depth, base, io, q, usr->user_flgs ); q += 4; /* user flags */ - DBG_RW_PCVAL("", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ + DBG_RW_PCVAL("sess_key ", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align, depth); /* logon server unicode string header */ q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align, depth); /* logon domain unicode string header */ - DBG_RW_IVAL("buffer_dom_id", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ - DBG_RW_PCVAL("padding", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ + DBG_RW_IVAL("buffer_dom_id ", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ + DBG_RW_PCVAL("padding ", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ DBG_RW_IVAL("num_other_sids", depth, base, io, q, usr->num_other_sids); q += 4; /* 0 - num_sids */ DBG_RW_IVAL("buffer_other_sids", depth, base, io, q, usr->buffer_other_sids); q += 4; /* NULL - undocumented pointer to SIDs. */ @@ -408,7 +408,7 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align, depth); /* home directory unicode string */ q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align, depth); /* home directory drive unicode string */ - DBG_RW_IVAL("num_groups2", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ + DBG_RW_IVAL("num_groups2 ", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ for (i = 0; i < usr->num_groups2; i++) { q = smb_io_gid(io, &(usr->gids[i]), q, base, align, depth); /* group info */ @@ -459,15 +459,15 @@ char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ q = smb_io_cred(io, &(r_l->srv_creds), q, base, align, depth); /* server credentials. server time stamp appears to be ignored. */ - DBG_RW_IVAL("buffer_user", depth, base, io, q, r_l->buffer_user); q += 4; + DBG_RW_IVAL("buffer_user ", depth, base, io, q, r_l->buffer_user); q += 4; if (r_l->buffer_user != 0) { q = lsa_io_user_info(io, r_l->user, q, base, align, depth); } - DBG_RW_IVAL("auth_resp", depth, base, io, q, r_l->auth_resp); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ + DBG_RW_IVAL("auth_resp ", depth, base, io, q, r_l->auth_resp); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ - DBG_RW_IVAL("status", depth, base, io, q, r_l->status); q += 4; + DBG_RW_IVAL("status ", depth, base, io, q, r_l->status); q += 4; return q; } @@ -504,7 +504,7 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ q = smb_io_cred(io, &(r_l->srv_creds), q, base, align, depth); /* server credentials. server time stamp appears to be ignored. */ - DBG_RW_IVAL("status", depth, base, io, q, r_l->status); q += 4; + DBG_RW_IVAL("status ", depth, base, io, q, r_l->status); q += 4; return q; } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index eb8215b7a33..173b3cdd060 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -504,7 +504,6 @@ static int make_rpc_reply(char *inbuf, char *q, int data_len) static int lsa_reply_open_policy(char *q, char *base) { int i; - char *start = q; LSA_R_OPEN_POL r_o; /* set up the LSA QUERY INFO response */ @@ -519,7 +518,7 @@ static int lsa_reply_open_policy(char *q, char *base) q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) @@ -593,7 +592,6 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, char *dom_name, char *dom_sid) { - char *start = q; LSA_R_QUERY_INFO r_q; /* set up the LSA QUERY INFO response */ @@ -609,7 +607,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, q = lsa_io_r_query(False, &r_q, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } /* pretty much hard-coded choice of "other" sids, unfortunately... */ @@ -693,7 +691,6 @@ static int lsa_reply_lookup_sids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_SIDS r_l; /* set up the LSA Lookup SIDs response */ @@ -705,7 +702,7 @@ static int lsa_reply_lookup_sids(char *q, char *base, q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static int lsa_reply_lookup_rids(char *q, char *base, @@ -713,7 +710,6 @@ static int lsa_reply_lookup_rids(char *q, char *base, char *dom_name, char *dom_sid, char *other_sid1, char *other_sid2, char *other_sid3) { - char *start = q; LSA_R_LOOKUP_RIDS r_l; /* set up the LSA Lookup RIDs response */ @@ -725,35 +721,35 @@ static int lsa_reply_lookup_rids(char *q, char *base, q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, DOM_CHAL *srv_chal, int status) { - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(r_c->srv_chal.data)); + DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); r_c->status = status; - - DEBUG(5,("make_lsa_r_req_chal srv_chal: %lx %lx\n", - *(uint32*)(&((r_c->srv_chal.data[0]))), - *(uint32*)(&((r_c->srv_chal.data[4]))) )); } static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DOM_CHAL *srv_chal) { - char *start = q; LSA_R_REQ_CHAL r_c; - /* set up the LSA REQUEST CHALLENGE response */ + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); + /* set up the LSA REQUEST CHALLENGE response */ make_lsa_r_req_chal(&r_c, srv_chal, 0); /* store the response in the SMB stream */ q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, @@ -767,7 +763,6 @@ static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, DOM_CHAL *resp_cred, int status) { - char *start = q; LSA_R_AUTH_2 r_a; /* set up the LSA AUTH 2 response */ @@ -778,7 +773,7 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, @@ -791,7 +786,6 @@ static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, DOM_CRED *srv_cred, int status) { - char *start = q; LSA_R_SRV_PWSET r_s; /* set up the LSA Server Password Set response */ @@ -801,7 +795,7 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void make_lsa_user_info(LSA_USER_INFO *usr, @@ -920,7 +914,6 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, DOM_CRED *srv_cred, LSA_USER_INFO *user_info) { - char *start = q; LSA_R_SAM_LOGON r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -936,7 +929,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } @@ -944,7 +937,6 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, DOM_CRED *srv_cred, uint32 status) { - char *start = q; LSA_R_SAM_LOGOFF r_s; /* XXXX maybe we want to say 'no', reject the client's credentials */ @@ -957,55 +949,41 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); /* return length of SMB data stored */ - return q - start; + return PTR_DIFF(q, base); } static void api_lsa_open_policy( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - /* we might actually want to decode the query, but it's not necessary */ /* lsa_io_q_open_policy(...); */ /* return a 20 byte policy handle */ - reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; + *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); } static void api_lsa_query_info( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_QUERY_INFO q_i; pstring dom_name; pstring dom_sid; /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, dom_name, dom_sid); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_sids( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_SIDS q_l; pstring dom_name; @@ -1013,7 +991,7 @@ static void api_lsa_lookup_sids( char *param, char *data, fstring dom_sids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1025,21 +1003,15 @@ static void api_lsa_lookup_sids( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, q_l.num_entries, dom_sids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } static void api_lsa_lookup_names( char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - int i; LSA_Q_LOOKUP_RIDS q_l; pstring dom_name; @@ -1047,7 +1019,7 @@ static void api_lsa_lookup_names( char *param, char *data, uint32 dom_rids[MAX_LOOKUP_SIDS]; /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0); pstrcpy(dom_name, lp_workgroup()); pstrcpy(dom_sid , lp_domainsid()); @@ -1060,14 +1032,10 @@ static void api_lsa_lookup_names( char *param, char *data, } /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, q_l.num_entries, dom_rids, /* text-converted SIDs */ dom_name, dom_sid, /* domain name, domain SID */ "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; } BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, @@ -1092,6 +1060,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENPOLICY\n")); api_lsa_open_policy(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1100,6 +1069,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, DEBUG(3,("LSA_QUERYINFOPOLICY\n")); api_lsa_query_info(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1161,6 +1131,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_OPENSECRET\n")); api_lsa_lookup_sids(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1168,6 +1139,7 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_LOOKUPNAMES\n")); api_lsa_lookup_names(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1180,11 +1152,16 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, return True; } -static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) +static BOOL update_dcinfo(int cnum, uint16 vuid, + struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) { - struct smb_passwd *smb_pass = get_smbpwnam(mach_acct); + struct smb_passwd *smb_pass; int i; + unbecome_user(); + smb_pass = get_smbpwnam(mach_acct); + become_user(cnum, vuid); + if (smb_pass != NULL) { memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); @@ -1219,43 +1196,39 @@ static BOOL update_dcinfo(struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acc dc->srv_chal.data[i] = 0xA5; } + DEBUG(6,("update_dcinfo: %d\n", __LINE__)); + return True; } -static void api_lsa_req_chal( user_struct *vuser, +static void api_lsa_req_chal( int cnum, uint16 vuid, + user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; - LSA_Q_REQ_CHAL q_r; fstring mach_acct; /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0); fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); strcat(mach_acct, "$"); - update_dcinfo(&(vuser->dc), &(q_r.clnt_chal), mach_acct); + update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, &(vuser->dc.srv_chal)); - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } static void api_lsa_auth_2( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_AUTH_2 q_a; DOM_CHAL srv_chal; @@ -1264,7 +1237,7 @@ static void api_lsa_auth_2( user_struct *vuser, srv_time.time = 0; /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0); /* check that the client credentials are valid */ cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, @@ -1274,13 +1247,8 @@ static void api_lsa_auth_2( user_struct *vuser, cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); /* construct reply. */ - reply_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, &srv_chal, 0x0); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1316,26 +1284,20 @@ static void api_lsa_srv_pwset( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SRV_PWSET q_a; DOM_CRED srv_cred; /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); /* construct reply. always indicate failure. nt keeps going... */ - reply_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, &srv_cred, NT_STATUS_WRONG_PASSWORD|0xC000000); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1343,26 +1305,20 @@ static void api_lsa_sam_logoff( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SAM_LOGOFF q_l; DOM_CRED srv_cred; /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); /* construct reply. always indicate success */ - reply_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata, &srv_cred, 0x0); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } @@ -1370,14 +1326,13 @@ static void api_lsa_sam_logon( user_struct *vuser, char *param, char *data, char **rdata, int *rdata_len ) { - int reply_len; LSA_Q_SAM_LOGON q_l; LSA_USER_INFO usr_info; LSA_USER_INFO *p_usr_info = NULL; DOM_CRED srv_creds; - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data + 0x18, 4, 0); + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0); /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); @@ -1454,208 +1409,11 @@ static void api_lsa_sam_logon( user_struct *vuser, NULL); /* char *other_sids */ } - reply_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata + 0x18, + *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, &srv_creds, p_usr_info); - - /* construct header, now that we know the reply length */ - reply_len += make_rpc_reply(data, *rdata, reply_len); - - *rdata_len = reply_len; } -#if 0 -case LSASAMLOGON: - DEBUG(1,("LSASAMLOGON\n")); - dump_data(1,data,128); - q = data + 0x18; - logonsrv = q + 16; - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = skip_unicode_string(logonsrv,1)+16; - q = align4(q, data); - unicomp = q; - q = skip_unicode_string(unicomp,1)+4; - DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n", - __LINE__, unistr(logonsrv), unistr(unicomp))); - q = align4(q, data); - rcvcred[0] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - rcvcred[1] = qIVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - clnttime = qIVAL; - checkcred(cnum, rcvcred[0], rcvcred[1], clnttime); - q += 2; - rtncred[0] = qIVAL; /* all these are ignored */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - rtncred[1] = qIVAL; - rtntime = qIVAL; - logonlevel = qSVAL; - DEBUG(1,("SMLOG %d\n", __LINE__)); - switchval = qSVAL; - switch (switchval) - { - case 1: - - q += 6; - domlen = qSVAL; - dommaxlen = qSVAL; q += 4; - paramcontrol = qIVAL; - logonid[0] = qIVAL; /* low part */ - logonid[1] = qIVAL; /* high part */ - - usernamelen = qSVAL; - - DEBUG(1,("SMLOG %d\n", __LINE__)); - usernamemaxlen = qSVAL; q += 4; - - DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n", - usernamelen, usernamemaxlen, dommaxlen)); - - dump_data(1,q,128); - - wslen = qSVAL; - wsmaxlen = qSVAL; q += 4; - rc4lmowfpass = q; q += 16; - rc4ntowfpass = q; q += 16; - - q += 12; domain = q; q += dommaxlen + 12; - q = align4(q, data); - username = q; q += usernamemaxlen + 12; - q = align4(q, data); - ws = q; - DEBUG(1,("domain=%s username=%s ws=%s\n", - unistr(domain), unistr(username), - unistr(ws))); - break; - default: - DEBUG(0,("unknown switch in SAMLOGON %d\n", - switchval)); - } - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]); - DEBUG(1,("userNAME %s [%s]\n", foo, username)); - DEBUG(1,("SMLOG %d\n", __LINE__)); - q = *rdata + 0x18; - qSIVAL(0x16a4b4); /* magic buffer pointer ? */ - makecred(cnum, clnttime+1, q); - dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1; - q += 8; - qSIVAL(0); /* timestamp. client doesn't care */ - qSSVAL(3); /* switch value 3. May be others? */ - qSSVAL(0); /* undocumented */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - - memset(rc4key, 0, sizeof rc4key); - SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]); - SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]); - DEBUG(1,("rc4ntowf %s\n", foo)); - arcfour_init(&c, rc4key, sizeof rc4key); - arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass); - for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]); - DEBUG(1,("ntowf %s\n", foo)); - - if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) { - qSIVAL(0); /* no buffer */ - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len); - break; - } - - qSIVAL(2); /* another magic bufptr? */ - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo)); - qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]); - qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]); - DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1])); - qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]); - qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]); - qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]); - qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]); - DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename)); - qunihdr(userinfo->effectivename); - qunihdr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunihdr(userinfo->logonscript); - qunihdr(userinfo->profilepath); - qunihdr(userinfo->homedirectory); - qunihdr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSSVAL(userinfo->logoncount); - qSSVAL(userinfo->badpwcount); - qSIVAL(userinfo->uid); - qSIVAL(userinfo->gid); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - qSIVAL(8); /* ptr to groups */ - qSIVAL(userinfo->userflags); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */ - qunihdr(userinfo->logonserver); - qunihdr(userinfo->logondomain); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(2); /* logon domain id ptr */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - memset(q,0,40); q += 40; /* expansion room */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->nsids); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(0); /* ptr to sids and values */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->effectivename); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->fullname); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->logonscript); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qunistr(userinfo->profilepath); - qunistr(userinfo->homedirectory); - qunistr(userinfo->homedirectorydrive); - DEBUG(1,("SMLOG %d\n", __LINE__)); - qSIVAL(userinfo->ngroups); - for (i = 0; i < userinfo->ngroups; i++) - { - qSIVAL(userinfo->groups[i].gid); - qSIVAL(userinfo->groups[i].attr); - } - qunistr(userinfo->logonserver); - qunistr(userinfo->logondomain); - for (i = 0; i < userinfo->nsids; i++) - { - /* put the extra sids: PAXX: TODO */ - } - /* Assumption. This is the only domain, sending our SID */ - /* PAXX: may want to do passthrough later */ - strcpy(domsid,lp_domainsid()); -DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid)); - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - revision = atoi(p); -DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision)); - identauth = atoi(strtok(0,"-")); -DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth)); - numsubauths = 0; - while (p = strtok(0, "-")) - subauths[numsubauths++] = atoi(p); - qSIVAL(numsubauths); - qSCVAL(revision); - qSCVAL(numsubauths); - qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */ - qRSIVAL(identauth); /* next 4 bytes */ - DEBUG(1,("SMLOG %d\n", __LINE__)); - for (i = 0; i < numsubauths; i++) - { - qSIVAL(subauths[i]); - } - qSCVAL(1); /* Authoratitive. Change if passthrough? */ - qSCVAL(0); /* pad for above boolean */ - qSSVAL(0); /* pad for above boolean */ - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; -#endif - BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -1687,7 +1445,8 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, case LSA_REQCHAL: { DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(vuser, param, data, rdata, rdata_len); + api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1695,6 +1454,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_AUTH2\n")); api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1702,6 +1462,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_SRVPWSET\n")); api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } @@ -1709,6 +1470,7 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, { DEBUG(3,("LSA_SAMLOGON\n")); api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; } diff --git a/source/smbparse.c b/source/smbparse.c index d7fbf53020e..ba3e073e5fb 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -53,7 +53,7 @@ char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align, int d q = align_offset(q, base, align); - DBG_RW_IVAL("low", depth, base, io, q, nttime->low ); q += 4; /* low part */ + DBG_RW_IVAL("low ", depth, base, io, q, nttime->low ); q += 4; /* low part */ DBG_RW_IVAL("high", depth, base, io, q, nttime->high); q += 4; /* high part */ return q; @@ -73,8 +73,8 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int q = align_offset(q, base, align); - DBG_RW_CVAL("sid_no", depth, base, io, q, sid->sid_no); q++; - DBG_RW_CVAL("num_auths", depth, base, io, q, sid->num_auths); q++; + DBG_RW_CVAL("sid_no ", depth, base, io, q, sid->sid_no); q++; + DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; for (i = 0; i < 6; i++) { @@ -86,7 +86,7 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int /* oops! XXXX should really issue a warning here... */ if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; - DBG_RW_PSVAL("num_auths", depth, base, io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; + DBG_RW_PSVAL("num_auths ", depth, base, io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; return q; } @@ -108,7 +108,7 @@ char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int de DBG_RW_IVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 4; DBG_RW_IVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 4; - DBG_RW_IVAL("undoc", depth, base, io, q, hdr->undoc ); q += 4; + DBG_RW_IVAL("undoc ", depth, base, io, q, hdr->undoc ); q += 4; return q; } @@ -176,7 +176,7 @@ char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int uni2->undoc = 0; DBG_RW_IVAL("uni_max_len", depth, base, io, q, uni2->uni_max_len); q += 4; - DBG_RW_IVAL("undoc", depth, base, io, q, uni2->undoc ); q += 4; + DBG_RW_IVAL("undoc ", depth, base, io, q, uni2->undoc ); q += 4; DBG_RW_IVAL("uni_str_len", depth, base, io, q, uni2->uni_str_len); q += 4; /* oops! XXXX maybe issue a warning that this is happening... */ @@ -185,7 +185,7 @@ char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int /* buffer advanced by indicated length of string NOT by searching for null-termination */ - DBG_RW_PSVAL("", depth, base, io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; + DBG_RW_PSVAL("buffer ", depth, base, io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; return q; } @@ -208,7 +208,7 @@ char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, i /* should be value 0, so enforce it */ sid2->undoc = 0; - DBG_RW_IVAL("type", depth, base, io, q, sid2->type ); q += 4; + DBG_RW_IVAL("type ", depth, base, io, q, sid2->type ); q += 4; DBG_RW_IVAL("undoc", depth, base, io, q, sid2->undoc); q += 4; q = smb_io_unihdr2(io, &(sid2->hdr), q, base, align, depth); @@ -235,9 +235,9 @@ char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, i /* should be value 5, so enforce it */ rid2->undoc = 5; - DBG_RW_IVAL("type", depth, base, io, q, rid2->type); q += 4; - DBG_RW_IVAL("undoc", depth, base, io, q, rid2->undoc ); q += 4; - DBG_RW_IVAL("rid", depth, base, io, q, rid2->rid ); q += 4; + DBG_RW_IVAL("type ", depth, base, io, q, rid2->type); q += 4; + DBG_RW_IVAL("undoc ", depth, base, io, q, rid2->undoc ); q += 4; + DBG_RW_IVAL("rid ", depth, base, io, q, rid2->rid ); q += 4; DBG_RW_IVAL("rid_idx", depth, base, io, q, rid2->rid_idx ); q += 4; return q; @@ -262,8 +262,7 @@ char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align DBG_RW_SVAL("sec_chan", depth, base, io, q, log->sec_chan); q += 2; - /* XXXX no alignment required between sec_chan and uni_comp_name */ - q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, 0, depth); + q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, align, depth); return q; } @@ -333,7 +332,7 @@ char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align q = align_offset(q, base, align); - DBG_RW_IVAL("low", depth, base, io, q, log->low ); q += 4; + DBG_RW_IVAL("low ", depth, base, io, q, log->low ); q += 4; DBG_RW_IVAL("high", depth, base, io, q, log->high); q += 4; return q; @@ -402,7 +401,7 @@ char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align q = smb_io_cred (io, &(sam->rtn_cred), q, base, align, depth); DBG_RW_IVAL("logon_level", depth, base, io, q, sam->logon_level); q += 4; - DBG_RW_SVAL("auth_level", depth, base, io, q, sam->auth_level ); q += 4; + DBG_RW_SVAL("auth_level ", depth, base, io, q, sam->auth_level ); q += 4; switch (sam->auth_level) { @@ -432,7 +431,7 @@ char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align, int dept q = align_offset(q, base, align); - DBG_RW_IVAL("gid", depth, base, io, q, gid->gid ); q += 4; + DBG_RW_IVAL("gid ", depth, base, io, q, gid->gid ); q += 4; DBG_RW_IVAL("attr", depth, base, io, q, gid->attr); q += 4; return q; @@ -451,17 +450,17 @@ char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align, int /* reserved should be zero: enforce it */ rpc->reserved = 0; - DBG_RW_CVAL("major", depth, base, io, q, rpc->major); q++; - DBG_RW_CVAL("minor", depth, base, io, q, rpc->minor); q++; - DBG_RW_CVAL("pkt_type", depth, base, io, q, rpc->pkt_type); q++; - DBG_RW_CVAL("frag", depth, base, io, q, rpc->frag); q++; - DBG_RW_IVAL("pack_type", depth, base, io, q, rpc->pack_type); q += 4; - DBG_RW_SVAL("frag_len", depth, base, io, q, rpc->frag_len); q += 2; - DBG_RW_SVAL("auth_len", depth, base, io, q, rpc->auth_len); q += 2; - DBG_RW_IVAL("call_id", depth, base, io, q, rpc->call_id); q += 4; + DBG_RW_CVAL("major ", depth, base, io, q, rpc->major); q++; + DBG_RW_CVAL("minor ", depth, base, io, q, rpc->minor); q++; + DBG_RW_CVAL("pkt_type ", depth, base, io, q, rpc->pkt_type); q++; + DBG_RW_CVAL("frag ", depth, base, io, q, rpc->frag); q++; + DBG_RW_IVAL("pack_type ", depth, base, io, q, rpc->pack_type); q += 4; + DBG_RW_SVAL("frag_len ", depth, base, io, q, rpc->frag_len); q += 2; + DBG_RW_SVAL("auth_len ", depth, base, io, q, rpc->auth_len); q += 2; + DBG_RW_IVAL("call_id ", depth, base, io, q, rpc->call_id); q += 4; DBG_RW_IVAL("alloc_hint", depth, base, io, q, rpc->alloc_hint); q += 4; DBG_RW_CVAL("context_id", depth, base, io, q, rpc->context_id); q++; - DBG_RW_CVAL("reserved", depth, base, io, q, rpc->reserved); q++; + DBG_RW_CVAL("reserved ", depth, base, io, q, rpc->reserved); q++; return q; } @@ -513,11 +512,11 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, DBG_RW_SVAL("uni_dom_max_len", depth, base, io, q, d_q->uni_dom_max_len); q += 2; /* domain name string length * 2 */ - DBG_RW_SVAL("padding", depth, base, io, q, d_q->padding ); q += 2; /* 2 padding bytes */ + DBG_RW_SVAL("padding ", depth, base, io, q, d_q->padding ); q += 2; /* 2 padding bytes */ DBG_RW_SVAL("uni_dom_str_len", depth, base, io, q, d_q->uni_dom_str_len); q += 2; /* domain name string length * 2 */ DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, d_q->buffer_dom_name); q += 4; /* undocumented domain name string buffer pointer */ - DBG_RW_IVAL("buffer_dom_sid", depth, base, io, q, d_q->buffer_dom_sid ); q += 4; /* undocumented domain SID string buffer pointer */ + DBG_RW_IVAL("buffer_dom_sid ", depth, base, io, q, d_q->buffer_dom_sid ); q += 4; /* undocumented domain SID string buffer pointer */ if (d_q->buffer_dom_name != 0) { @@ -545,11 +544,11 @@ char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align, q = align_offset(q, base, align); - DBG_RW_IVAL("undoc_buffer", depth, base, io, q, r_r->undoc_buffer); q += 4; /* undocumented buffer pointer. */ - DBG_RW_IVAL("num_ref_doms_1", depth, base, io, q, r_r->num_ref_doms_1); q += 4; /* num referenced domains? */ + DBG_RW_IVAL("undoc_buffer ", depth, base, io, q, r_r->undoc_buffer); q += 4; /* undocumented buffer pointer. */ + DBG_RW_IVAL("num_ref_doms_1 ", depth, base, io, q, r_r->num_ref_doms_1); q += 4; /* num referenced domains? */ DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, r_r->buffer_dom_name); q += 4; /* undocumented domain name buffer pointer. */ - DBG_RW_IVAL("max_entries", depth, base, io, q, r_r->max_entries); q += 4; /* 32 - max number of entries */ - DBG_RW_IVAL("num_ref_doms_2", depth, base, io, q, r_r->num_ref_doms_2); q += 4; /* 4 - num referenced domains? */ + DBG_RW_IVAL("max_entries ", depth, base, io, q, r_r->max_entries); q += 4; /* 32 - max number of entries */ + DBG_RW_IVAL("num_ref_doms_2 ", depth, base, io, q, r_r->num_ref_doms_2); q += 4; /* 4 - num referenced domains? */ q = smb_io_unihdr2(io, &(r_r->hdr_dom_name), q, base, align, depth); /* domain name unicode string header */ diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index d20ff42c0e8..31ac9e351be 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -396,9 +396,9 @@ static void usage(char *name) /* Set read buffer to 16k for effiecient reads */ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - + /* need locking permission on smbpasswd file */ + chmod(pfile, 0666); + /* Lock the smbpasswd file for write. */ if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) { err = errno; -- cgit From 28d96c7e6de19a28346d406ccc6fc8b00305903b Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 12:55:07 +0000 Subject: checked in a file with a compile error. oops! --- source/smbd/pipes.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 173b3cdd060..772e49f41d1 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -739,7 +739,6 @@ static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); /* set up the LSA REQUEST CHALLENGE response */ make_lsa_r_req_chal(&r_c, srv_chal, 0); -- cgit From 69fad04198bfcbaaadcebd6c81efdb3612af5bc8 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Mon, 13 Oct 1997 13:00:59 +0000 Subject: JHT ==> Getting ready for 1.9.18alpha1. examples/smb.conf.default: added line "share modes = no" to netlogon share parameter list packaging/redhat: updated RedHat RPM build files. added smbadduser script (modified for RHL). --- examples/smb.conf.default | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 7de2c21768b..9ab5e755ce1 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -135,6 +135,7 @@ ; writable = no ; For browseable say NO if you want to hide the NETLOGON share ; browseable = yes +; share modes = no ; Un-comment the following to provide a specific roving profile share ; the default is to use the user's home directory -- cgit From a3f96555b47265b8cd4d1f735af58375e2591d56 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 13:35:37 +0000 Subject: debug info added --- source/include/byteorder.h | 14 +++++++------- source/libsmb/credentials.c | 43 ++++++++++++++++++++++++++++++++++++------- source/smbd/pipes.c | 4 ++++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index 808026f9dbd..a6f826b518d 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -200,30 +200,30 @@ it also defines lots of intermediate macros, just ignore those :-) #define DBG_RW_PCVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PCVAL(read,inbuf,outbuf,len) \ - DEBUG(5,("%s %04x %s: ", \ + DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%x ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_PSVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PSVAL(read,inbuf,outbuf,len) \ - DEBUG(5,("%s %04x %s: ", \ + DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%d ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ RW_CVAL(read,inbuf,outbuf,0) \ - DEBUG(5,("%s %04x %s: %02x\n", \ + DEBUG(5,("%s%04x %s: %02x\n", \ tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); #define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \ RW_SVAL(read,inbuf,outbuf,0) \ - DEBUG(5,("%s %04x %s: %04x\n", \ + DEBUG(5,("%s%04x %s: %04x\n", \ tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); #define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \ RW_IVAL(read,inbuf,outbuf,0) \ - DEBUG(5,("%s %04x %s: %08x\n", \ + DEBUG(5,("%s%04x %s: %08x\n", \ tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index ce7159f7ffa..3af182c5db8 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -37,13 +37,6 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, char sum2[8]; char buf[8]; - DEBUG(4,("cred_session_key\n")); - - DEBUG(5,(" clnt_chal: %lx %lx srv_chal: %lx %lx\n", - - IVAL(clnt_chal->data, 0), IVAL(clnt_chal->data, 4), - IVAL(srv_chal->data, 0), IVAL(srv_chal->data, 4))); - sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); @@ -53,6 +46,18 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, smbhash(pass , sum2, buf); smbhash(pass+9, buf , session_key); + /* debug output*/ + DEBUG(4,("cred_session_key\n")); + + DEBUG(5,(" clnt_chal: ")); + dump_data(5, clnt_chal->data, 8); + + DEBUG(5,(" srv_chal: ")); + dump_data(5, srv_chal->data, 8); + + DEBUG(5,(" clnt_chal+srv_chal: ")); + dump_data(5, sum2, 8); + DEBUG(5,(" session_key: ")); dump_data(5, session_key, 16); } @@ -83,6 +88,21 @@ void cred_create(char *session_key, DOM_CHAL *stored_cred, UTIME timestamp, memset(key2, 0, 7); key2[0] = session_key[7]; smbhash(key2, buf, cred->data); + + /* debug output*/ + DEBUG(4,("cred_create\n")); + + DEBUG(5,(" session_key: ")); + dump_data(5, session_key, 16); + + DEBUG(5,(" stored_cred: ")); + dump_data(5, stored_cred->data, 8); + + DEBUG(5,(" timecred: ")); + dump_data(5, timecred, 8); + + DEBUG(5,(" cred: ")); + dump_data(5, cred->data, 8); } @@ -106,6 +126,15 @@ int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, cred_create(session_key, stored_cred, timestamp, &cred2); + /* debug output*/ + DEBUG(4,("cred_assert\n")); + + DEBUG(5,(" challenge: ")); + dump_data(5, cred->data, 16); + + DEBUG(5,(" calculated: ")); + dump_data(5, cred2.data, 8); + return memcmp(cred->data, cred2.data, 8) == 0; } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 772e49f41d1..59592a04ae3 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -1164,6 +1164,8 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, if (smb_pass != NULL) { memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); + DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw))); + dump_data(5, dc->md4pw, 16); } else { @@ -1218,6 +1220,8 @@ static void api_lsa_req_chal( int cnum, uint16 vuid, update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); + DEBUG(6,("api_lsa_req_chal: %d\n", __LINE__)); + /* construct reply. return status is always 0x0 */ *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, &(vuser->dc.srv_chal)); -- cgit From 3fc48246ee0d89ad2f10f050d2d68af53446129f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 13 Oct 1997 13:49:50 +0000 Subject: reverted a change made by Luke at his request. Luke, when you don't know what has been changed in the CVS tree I highly recommend you point your browser at: http://samba.anu.edu.au/cgi-bin/cvsweb/samba/source If you click on a filename you can then see all the commits and changes that have been made to it over time. You can also download any version of the file or find the differences between any two versions. All of this is not dependent on the state of your local CVS sandbox, so it can be used to find out the "true" state of the tree at any time. If you suspect some sort of CVS problem (like a change getting reverted) then please use the above URL to work out what has happened. You should be able to see exactly who made what changes and when. --- source/utils/smbpasswd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 31ac9e351be..a4c25417ca2 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -396,8 +396,8 @@ static void usage(char *name) /* Set read buffer to 16k for effiecient reads */ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - /* need locking permission on smbpasswd file */ - chmod(pfile, 0666); + /* make sure it is only rw by the owner */ + chmod(pfile, 0600); /* Lock the smbpasswd file for write. */ if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) { -- cgit From d7a9a02e0a9e1e791810c24bcfcbd39a6bd7dac5 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 14:19:17 +0000 Subject: debugging... no idea what i'm doing. --- source/libsmb/credentials.c | 2 +- source/smbd/pipes.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index 3af182c5db8..3355ab17040 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -130,7 +130,7 @@ int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, DEBUG(4,("cred_assert\n")); DEBUG(5,(" challenge: ")); - dump_data(5, cred->data, 16); + dump_data(5, cred->data, 8); DEBUG(5,(" calculated: ")); dump_data(5, cred2.data, 8); diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 59592a04ae3..74bde7493d6 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -1181,13 +1181,9 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, DEBUG(4,("pass %s %s\n", mach_acct, foo)); } - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), - dc->md4pw, dc->sess_key); - - /* copy the client credentials for later use */ - memcpy(dc->srv_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); - memcpy(dc->srv_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); + /* copy the client credentials */ + memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); /* create a server challenge for the client */ /* PAXX: set these to random values. */ @@ -1197,6 +1193,10 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, dc->srv_chal.data[i] = 0xA5; } + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), + dc->md4pw, dc->sess_key); + DEBUG(6,("update_dcinfo: %d\n", __LINE__)); return True; @@ -1218,9 +1218,10 @@ static void api_lsa_req_chal( int cnum, uint16 vuid, strcat(mach_acct, "$"); - update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); + DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); + dump_data(6, q_r.clnt_chal.data, 8); - DEBUG(6,("api_lsa_req_chal: %d\n", __LINE__)); + update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); /* construct reply. return status is always 0x0 */ *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, -- cgit From 8fe02c239d70497af449ed0cdf1a32de10021ba1 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 15:55:54 +0000 Subject: split pipes.c down into util, netlog and ntlsa. --- source/include/proto.h | 36 +- source/pipenetlog.c | 610 ++++++++++++++++++++++++++ source/pipentlsa.c | 408 +++++++++++++++++ source/pipeutil.c | 213 +++++++++ source/smbd/pipes.c | 1136 +----------------------------------------------- 5 files changed, 1261 insertions(+), 1142 deletions(-) create mode 100644 source/pipenetlog.c create mode 100644 source/pipentlsa.c create mode 100644 source/pipeutil.c diff --git a/source/include/proto.h b/source/include/proto.h index 72b15173ecc..324431e2b3d 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -626,27 +626,49 @@ BOOL server_validate(char *buf); BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname); void pcap_printer_fn(void (*fn)()); -/*The following definitions come from pipes.c */ +/*The following definitions come from pipenetlog.c */ -int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize); -BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, + +/*The following definitions come from pipentlsa.c */ + +BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -char *dom_sid_to_string(DOM_SID *sid); -BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, + +/*The following definitions come from pipes.c */ + +int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize); +BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, +void LsarpcTNP1(char *data,char **rdata, int *rdata_len); +BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); +/*The following definitions come from pipeutil.c */ + +void initrpcreply(char *inbuf, char *q); +void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen); +uint32 name_to_rid(char *user_name); +char *dom_sid_to_string(DOM_SID *sid); +void make_dom_sid(DOM_SID *sid, char *domsid); +void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len); +int make_rpc_reply(char *inbuf, char *q, int data_len); +void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate); +void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate); +void make_unistr(UNISTR *str, char *buf); +void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate); +void make_dom_rid2(DOM_RID2 *rid2, uint32 rid); +void make_dom_sid2(DOM_SID2 *sid2, char *sid_str); + /*The following definitions come from predict.c */ int read_predict(int fd,int offset,char *buf,char **ptr,int num); diff --git a/source/pipenetlog.c b/source/pipenetlog.c new file mode 100644 index 00000000000..ef5acdc5450 --- /dev/null +++ b/source/pipenetlog.c @@ -0,0 +1,610 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Pipe SMB reply routines + Copyright (C) Andrew Tridgell 1992-1997, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 1997. + + 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 reply_ calls on named pipes that the server + makes to handle specific protocols +*/ + + +#include "includes.h" +#include "trans2.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + +#ifdef NTDOMAIN + +static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, + DOM_CHAL *srv_chal, int status) +{ + DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); + r_c->status = status; +} + +static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, + DOM_CHAL *srv_chal) +{ + LSA_R_REQ_CHAL r_c; + + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + + /* set up the LSA REQUEST CHALLENGE response */ + make_lsa_r_req_chal(&r_c, srv_chal, 0); + + /* store the response in the SMB stream */ + q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); + + DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, + DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) +{ + memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); + memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); + r_a->status = status; +} + +static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, + DOM_CHAL *resp_cred, int status) +{ + LSA_R_AUTH_2 r_a; + + /* set up the LSA AUTH 2 response */ + + make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + + /* store the response in the SMB stream */ + q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, + DOM_CRED *srv_cred, int status) +{ + memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); + r_a->status = status; +} + +static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, + DOM_CRED *srv_cred, int status) +{ + LSA_R_SRV_PWSET r_s; + + /* set up the LSA Server Password Set response */ + make_lsa_r_srv_pwset(&r_s, srv_cred, status); + + /* store the response in the SMB stream */ + q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static void make_lsa_user_info(LSA_USER_INFO *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *logon_script, + char *profile_path, + char *home_dir, + char *dir_drive, + + uint16 logon_count, + uint16 bad_pw_count, + + uint32 user_id, + uint32 group_id, + uint32 num_groups, + DOM_GID *gids, + uint32 user_flgs, + + char sess_key[16], + + char *logon_srv, + char *logon_dom, + + char *dom_sid, + char *other_sids) /* space-delimited set of SIDs */ +{ + /* only cope with one "other" sid, right now. */ + /* need to count the number of space-delimited sids */ + int i; + int num_other_sids = other_sids != NULL ? 1 : 0; + + int len_user_name = strlen(user_name ); + int len_full_name = strlen(full_name ); + int len_logon_script = strlen(logon_script); + int len_profile_path = strlen(profile_path); + int len_home_dir = strlen(home_dir ); + int len_dir_drive = strlen(dir_drive ); + + int len_logon_srv = strlen(logon_srv); + int len_logon_dom = strlen(logon_dom); + + usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ + + usr->logon_time = *logon_time; + usr->logoff_time = *logoff_time; + usr->kickoff_time = *kickoff_time; + usr->pass_last_set_time = *pass_last_set_time; + usr->pass_can_change_time = *pass_can_change_time; + usr->pass_must_change_time = *pass_must_change_time; + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); + + usr->logon_count = logon_count; + usr->bad_pw_count = bad_pw_count; + + usr->user_id = user_id; + usr->group_id = group_id; + usr->num_groups = num_groups; + usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ + usr->user_flgs = user_flgs; + + if (sess_key != NULL) + { + memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); + } + else + { + bzero(usr->sess_key, sizeof(usr->sess_key)); + } + + make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); + make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); + + usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ + + bzero(usr->padding, sizeof(usr->padding)); + + usr->num_other_sids = num_other_sids; + usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); + + usr->num_groups2 = num_groups; + for (i = 0; i < num_groups; i++) + { + usr->gids[i] = gids[i]; + } + + make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); + make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); + + make_dom_sid(&(usr->dom_sid), dom_sid); + make_dom_sid(&(usr->other_sids[0]), other_sids); +} + + +static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, + DOM_CRED *srv_cred, LSA_USER_INFO *user_info) +{ + LSA_R_SAM_LOGON r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + + /* store the user information, if there is any. */ + r_s.user = user_info; + r_s.buffer_user = user_info != NULL ? 1 : 0; + r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + + +static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, + DOM_CRED *srv_cred, + uint32 status) +{ + LSA_R_SAM_LOGOFF r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + + r_s.status = status; + + /* store the response in the SMB stream */ + q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + + +static BOOL update_dcinfo(int cnum, uint16 vuid, + struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) +{ + struct smb_passwd *smb_pass; + int i; + + unbecome_user(); + smb_pass = get_smbpwnam(mach_acct); + become_user(cnum, vuid); + + if (smb_pass != NULL) + { + memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); + DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw))); + dump_data(5, dc->md4pw, 16); + } + else + { + /* No such machine account. Should error out here, but we'll + print and carry on */ + DEBUG(1,("No account in domain for %s\n", mach_acct)); + return False; + } + + { + char foo[16]; + for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); + DEBUG(4,("pass %s %s\n", mach_acct, foo)); + } + + /* copy the client credentials */ + memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); + + /* create a server challenge for the client */ + /* PAXX: set these to random values. */ + /* lkcl: paul, you mentioned that it doesn't really matter much */ + for (i = 0; i < 8; i++) + { + dc->srv_chal.data[i] = 0xA5; + } + + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), + dc->md4pw, dc->sess_key); + + DEBUG(6,("update_dcinfo: %d\n", __LINE__)); + + return True; +} + +static void api_lsa_req_chal( int cnum, uint16 vuid, + user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_REQ_CHAL q_r; + + fstring mach_acct; + + /* grab the challenge... */ + lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0); + + fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); + + strcat(mach_acct, "$"); + + DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); + dump_data(6, q_r.clnt_chal.data, 8); + + update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); + + /* construct reply. return status is always 0x0 */ + *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, + &(vuser->dc.srv_chal)); + +} + +static void api_lsa_auth_2( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_AUTH_2 q_a; + + DOM_CHAL srv_chal; + UTIME srv_time; + + srv_time.time = 0; + + /* grab the challenge... */ + lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0); + + /* check that the client credentials are valid */ + cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, + &(vuser->dc.srv_cred), srv_time); + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); + + /* construct reply. */ + *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, + &srv_chal, 0x0); +} + + +static BOOL deal_with_credentials(user_struct *vuser, + DOM_CRED *clnt_cred, DOM_CRED *srv_cred) +{ + UTIME new_clnt_time; + + /* doesn't matter that server time is 0 */ + srv_cred->timestamp.time = 0; + + /* check that the client credentials are valid */ + if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, + &(vuser->dc.srv_cred), clnt_cred->timestamp)) + { + return False; + } + + /* increment client time by one second */ + new_clnt_time.time = clnt_cred->timestamp.time + 1; + + /* create server credentials for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, + &(srv_cred->challenge)); + + /* update the client and server credentials, for use next time... */ + *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + + return True; +} + +static void api_lsa_srv_pwset( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_SRV_PWSET q_a; + + DOM_CRED srv_cred; + + /* grab the challenge and encrypted password ... */ + lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); + + /* construct reply. always indicate failure. nt keeps going... */ + *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, + &srv_cred, + NT_STATUS_WRONG_PASSWORD|0xC000000); +} + + +static void api_lsa_sam_logoff( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_SAM_LOGOFF q_l; + + DOM_CRED srv_cred; + + /* grab the challenge... */ + lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); + + /* construct reply. always indicate success */ + *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata, + &srv_cred, + 0x0); +} + + +static void api_lsa_sam_logon( user_struct *vuser, + char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_SAM_LOGON q_l; + LSA_USER_INFO usr_info; + LSA_USER_INFO *p_usr_info = NULL; + + DOM_CRED srv_creds; + + lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0); + + /* checks and updates credentials. creates reply credentials */ + deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); + + if (vuser != NULL) + { + NTTIME dummy_time; + pstring logon_script; + pstring profile_path; + pstring home_dir; + pstring home_drive; + pstring my_name; + pstring my_workgroup; + pstring dom_sid; + pstring username; + extern pstring myname; + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + get_myname(myname, NULL); + + pstrcpy(logon_script, lp_logon_script()); + pstrcpy(profile_path, lp_logon_path ()); + pstrcpy(dom_sid , lp_domainsid ()); + pstrcpy(my_workgroup, lp_workgroup ()); + + pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); + pstrcpy(my_name , myname ); + strupper(my_name); + + pstrcpy(home_drive , "a:" ); + +#if (defined(NETGROUP) && defined(AUTOMOUNT)) + pstrcpy(home_dir , vuser->home_share); +#else + pstrcpy(home_dir , "\\\\%L\\%U"); + standard_sub_basic(home_dir); +#endif + + p_usr_info = &usr_info; + + make_lsa_user_info(p_usr_info, + + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ + + username, /* user_name */ + vuser->real_name, /* full_name */ + logon_script, /* logon_script */ + profile_path, /* profile_path */ + home_dir, /* home_dir */ + home_drive, /* dir_drive */ + + 0, /* logon_count */ + 0, /* bad_pw_count */ + + vuser->uid, /* uint32 user_id */ + vuser->gid, /* uint32 group_id */ + 0, /* uint32 num_groups */ + NULL, /* DOM_GID *gids */ + 0x20, /* uint32 user_flgs */ + + NULL, /* char sess_key[16] */ + + my_name, /* char *logon_srv */ + my_workgroup, /* char *logon_dom */ + + dom_sid, /* char *dom_sid */ + NULL); /* char *other_sids */ + } + + *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, + &srv_creds, p_usr_info); +} + + +BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + int pkttype = CVAL(data, 2); + + user_struct *vuser; + + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); + + if ((vuser = get_valid_user_struct(uid)) == NULL) return False; + + DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); +#if defined(NETGROUP) && defined(AUTOMOUNT) + DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); +#endif + + switch (opnum) + { + case LSA_REQCHAL: + { + DEBUG(3,("LSA_REQCHAL\n")); + api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_AUTH2: + { + DEBUG(3,("LSA_AUTH2\n")); + api_lsa_auth_2(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_SRVPWSET: + { + DEBUG(3,("LSA_SRVPWSET\n")); + api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_SAMLOGON: + { + DEBUG(3,("LSA_SAMLOGON\n")); + api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_SAMLOGOFF: + { + DEBUG(3,("LSA_SAMLOGOFF\n")); + api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len); + break; + } + + default: + { + DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); + break; + } + } + + return True; +} + +#endif /* NTDOMAIN */ diff --git a/source/pipentlsa.c b/source/pipentlsa.c new file mode 100644 index 00000000000..55deffabd6f --- /dev/null +++ b/source/pipentlsa.c @@ -0,0 +1,408 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Pipe SMB reply routines + Copyright (C) Andrew Tridgell 1992-1997, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 1997. + + 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 reply_ calls on named pipes that the server + makes to handle specific protocols +*/ + + +#include "includes.h" +#include "trans2.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + +#ifdef NTDOMAIN + +static int lsa_reply_open_policy(char *q, char *base) +{ + int i; + LSA_R_OPEN_POL r_o; + + /* set up the LSA QUERY INFO response */ + /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ + for (i = 0; i < POL_HND_SIZE; i++) + { + r_o.pol.data[i] = i; + } + r_o.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +{ + int domlen = strlen(dom_name); + + d_q->uni_dom_max_len = domlen * 2; + d_q->padding = 0; + d_q->uni_dom_str_len = domlen * 2; + + d_q->buffer_dom_name = 0; /* domain buffer pointer */ + d_q->buffer_dom_sid = 0; /* domain sid pointer */ + + /* NOT null-terminated: 4-terminated instead! */ + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + + make_dom_sid(&(d_q->dom_sid), dom_sid); +} + +static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, + char *dom_name, char *dom_sid) +{ + LSA_R_QUERY_INFO r_q; + + /* set up the LSA QUERY INFO response */ + + r_q.undoc_buffer = 1; /* not null */ + r_q.info_class = q_q->info_class; + + make_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_query(False, &r_q, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +/* pretty much hard-coded choice of "other" sids, unfortunately... */ +static void make_dom_ref(DOM_R_REF *ref, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int len_dom_name = strlen(dom_name); + int len_other_sid1 = strlen(other_sid1); + int len_other_sid2 = strlen(other_sid2); + int len_other_sid3 = strlen(other_sid3); + + ref->undoc_buffer = 1; + ref->num_ref_doms_1 = 4; + ref->buffer_dom_name = 1; + ref->max_entries = 32; + ref->num_ref_doms_2 = 4; + + make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); + make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); + + if (dom_name != NULL) + { + make_unistr(&(ref->uni_dom_name), dom_name); + } + + make_dom_sid(&(ref->ref_dom[0]), dom_sid ); + make_dom_sid(&(ref->ref_dom[1]), other_sid1); + make_dom_sid(&(ref->ref_dom[2]), other_sid2); + make_dom_sid(&(ref->ref_dom[3]), other_sid3); +} + +static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); + } + + r_l->num_entries3 = num_entries; +} + +static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); + } + + r_l->num_entries3 = num_entries; +} + +static int lsa_reply_lookup_sids(char *q, char *base, + int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_SIDS r_l; + + /* set up the LSA Lookup SIDs response */ + make_reply_lookup_sids(&r_l, num_entries, dom_sids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static int lsa_reply_lookup_rids(char *q, char *base, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_RIDS r_l; + + /* set up the LSA Lookup RIDs response */ + make_reply_lookup_rids(&r_l, num_entries, dom_rids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +static void api_lsa_open_policy( char *param, char *data, + char **rdata, int *rdata_len ) +{ + /* we might actually want to decode the query, but it's not necessary */ + /* lsa_io_q_open_policy(...); */ + + /* return a 20 byte policy handle */ + *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); +} + +static void api_lsa_query_info( char *param, char *data, + char **rdata, int *rdata_len ) +{ + LSA_Q_QUERY_INFO q_i; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* construct reply. return status is always 0x0 */ + *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, + dom_name, dom_sid); +} + +static void api_lsa_lookup_sids( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int i; + LSA_Q_LOOKUP_SIDS q_l; + pstring dom_name; + pstring dom_sid; + fstring dom_sids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received SIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); + } + + /* construct reply. return status is always 0x0 */ + *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, + q_l.num_entries, dom_sids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +static void api_lsa_lookup_names( char *param, char *data, + char **rdata, int *rdata_len ) +{ + int i; + LSA_Q_LOOKUP_RIDS q_l; + pstring dom_name; + pstring dom_sid; + uint32 dom_rids[MAX_LOOKUP_SIDS]; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domainsid()); + + /* convert received RIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + char *user_name = unistr2(q_l.lookup_name[i].str.buffer); + dom_rids[i] = name_to_rid(user_name); + } + + /* construct reply. return status is always 0x0 */ + *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, + q_l.num_entries, dom_rids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum = SVAL(data,22); + + int pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("netlogon rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); + switch (opnum) + { + case LSA_OPENPOLICY: + { + DEBUG(3,("LSA_OPENPOLICY\n")); + api_lsa_open_policy(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_QUERYINFOPOLICY: + { + DEBUG(3,("LSA_QUERYINFOPOLICY\n")); + + api_lsa_query_info(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_ENUMTRUSTDOM: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_ENUMTRUSTDOM\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); /* enumeration context */ + SIVAL(q, 0, 4); /* entries read */ + SIVAL(q, 0, 8); /* trust information */ + + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); + + break; + } + + case LSA_CLOSE: + { + char *q = *rdata + 0x18; + + DEBUG(3,("LSA_CLOSE\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + + break; + } + + case LSA_OPENSECRET: + { + char *q = *rdata + 0x18; + DEBUG(3,("LSA_OPENSECRET\n")); + + initrpcreply(data, *rdata); + + SIVAL(q, 0, 0); + SIVAL(q, 0, 4); + SIVAL(q, 0, 8); + SIVAL(q, 0, 12); + SIVAL(q, 0, 16); + + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); + + break; + } + + case LSA_LOOKUPSIDS: + { + DEBUG(3,("LSA_OPENSECRET\n")); + api_lsa_lookup_sids(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + case LSA_LOOKUPNAMES: + { + DEBUG(3,("LSA_LOOKUPNAMES\n")); + api_lsa_lookup_names(param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); + break; + } + + default: + { + DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); + break; + } + } + return True; +} + +#endif /* NTDOMAIN */ diff --git a/source/pipeutil.c b/source/pipeutil.c new file mode 100644 index 00000000000..ce3f1535c4c --- /dev/null +++ b/source/pipeutil.c @@ -0,0 +1,213 @@ + +/* + Unix SMB/Netbios implementation. + Version 1.9. + Pipe SMB utility routines + Copyright (C) Andrew Tridgell 1992-1997, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 1997. + + 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 reply_ calls on named pipes that the server + makes to handle specific protocols +*/ + + +#include "includes.h" +#include "trans2.h" + +extern int DEBUGLEVEL; + +/* this function is due to be replaced */ +void initrpcreply(char *inbuf, char *q) +{ + uint32 callid; + + SCVAL(q, 0, 5); q++; /* RPC version 5 */ + SCVAL(q, 0, 0); q++; /* minor version 0 */ + SCVAL(q, 0, 2); q++; /* RPC response packet */ + SCVAL(q, 0, 3); q++; /* first frag + last frag */ + RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ + RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ + SSVAL(q, 0, 0); q += 2; /* authentication length */ + callid = RIVAL(inbuf, 12); + RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ + SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ + SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ + SCVAL(q, 0, 0); q++; /* cancel count */ + SCVAL(q, 0, 0); q++; /* reserved */ +} + +/* this function is due to be replaced */ +void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) +{ + SSVAL(q, 8, datalen + 4); + SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ + SIVAL(q, datalen, rtnval); + *rlen = datalen + 4; + { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } +} + +/* RID username mapping function. just for fun, it maps to the unix uid */ +uint32 name_to_rid(char *user_name) +{ + struct passwd *pw = Get_Pwnam(user_name, False); + if (!pw) + { + DEBUG(1,("Username %s is invalid on this system\n", user_name)); + return (uint32)(-1); + } + + return (uint32)(pw->pw_uid); +} + + +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +char *dom_sid_to_string(DOM_SID *sid) +{ + static pstring sidstr; + char subauth[16]; + int i; + uint32 ia = (sid->id_auth[0]) + + (sid->id_auth[1] << 8 ) + + (sid->id_auth[2] << 16) + + (sid->id_auth[3] << 24); + + sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); + + for (i = 0; i < sid->num_auths; i++) + { + sprintf(subauth, "-%d", sid->sub_auths[i]); + strcat(sidstr, subauth); + } + + DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); + return sidstr; +} + +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +/* identauth >= 2^32 can be detected because it will be specified in hex */ +void make_dom_sid(DOM_SID *sid, char *domsid) +{ + int identauth; + char *p; + + DEBUG(4,("netlogon domain SID: %s\n", domsid)); + + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + sid->sid_no = atoi(p); + + /* identauth in decimal should be < 2^32 */ + /* identauth in hex should be >= 2^32 */ + identauth = atoi(strtok(0,"-")); + + DEBUG(4,("netlogon rev %d\n", sid->sid_no)); + DEBUG(4,("netlogon %s ia %d\n", p, identauth)); + + sid->id_auth[0] = 0; + sid->id_auth[1] = 0; + sid->id_auth[2] = (identauth & 0xff000000) >> 24; + sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; + sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; + sid->id_auth[5] = (identauth & 0x000000ff); + + sid->num_auths = 0; + + while ((p = strtok(0, "-")) != NULL) + { + sid->sub_auths[sid->num_auths++] = atoi(p); + } +} + +void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) +{ + if (hdr == NULL) return; + + hdr->major = 5; /* RPC version 5 */ + hdr->minor = 0; /* minor version 0 */ + hdr->pkt_type = 2; /* RPC response packet */ + hdr->frag = 3; /* first frag + last frag */ + hdr->pack_type = 1; /* packed data representation */ + hdr->frag_len = data_len; /* fragment length, fill in later */ + hdr->auth_len = 0; /* authentication length */ + hdr->call_id = call_id; /* call identifier - match incoming RPC */ + hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ + hdr->context_id = 0; /* presentation context identifier */ + hdr->cancel_count = 0; /* cancel count */ + hdr->reserved = 0; /* reserved */ +} + +int make_rpc_reply(char *inbuf, char *q, int data_len) +{ + uint32 callid = RIVAL(inbuf, 12); + RPC_HDR hdr; + + create_rpc_reply(&hdr, callid, data_len); + return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q; +} + +void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) +{ + hdr->uni_max_len = max_len; + hdr->uni_str_len = len; + hdr->undoc = terminate; +} + +void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) +{ + make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); + hdr->undoc_buffer = len > 0 ? 1 : 0; +} + +void make_unistr(UNISTR *str, char *buf) +{ + /* store the string (null-terminated copy) */ + PutUniCode((char *)(str->buffer), buf); +} + +void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = len + (terminate != 0 ? 1 : 0); + str->undoc = 0; + str->uni_str_len = len; + + /* store the string (null-terminated copy) */ + PutUniCode((char *)str->buffer, buf); + + /* overwrite the last character: some strings are terminated with 4 not 0 */ + str->buffer[len] = (uint16)terminate; +} + +void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) +{ + rid2->type = 0x5; + rid2->undoc = 0x5; + rid2->rid = rid; + rid2->rid_idx = 0; +} + +void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) +{ + int len_sid_str = strlen(sid_str); + + sid2->type = 0x5; + sid2->undoc = 0; + make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); + make_unistr (&(sid2->str), sid_str); +} diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 74bde7493d6..91ca69c0226 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -28,7 +28,6 @@ #include "includes.h" #include "trans2.h" -#include "nterr.h" #define PIPE "\\PIPE\\" #define PIPELEN strlen(PIPE) @@ -216,7 +215,7 @@ BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, TransactNamedPipe on \PIPE\lsarpc. ****************************************************************************/ -static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) +void LsarpcTNP1(char *data,char **rdata, int *rdata_len) { uint32 dword1, dword2; char pname[] = "\\PIPE\\lsass"; @@ -363,1136 +362,3 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } - - -#ifdef NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - -/* this function is due to be replaced */ -static void initrpcreply(char *inbuf, char *q) -{ - uint32 callid; - - SCVAL(q, 0, 5); q++; /* RPC version 5 */ - SCVAL(q, 0, 0); q++; /* minor version 0 */ - SCVAL(q, 0, 2); q++; /* RPC response packet */ - SCVAL(q, 0, 3); q++; /* first frag + last frag */ - RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ - RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ - SSVAL(q, 0, 0); q += 2; /* authentication length */ - callid = RIVAL(inbuf, 12); - RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ - SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ - SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ - SCVAL(q, 0, 0); q++; /* cancel count */ - SCVAL(q, 0, 0); q++; /* reserved */ -} - -/* this function is due to be replaced */ -static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) -{ - SSVAL(q, 8, datalen + 4); - SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ - SIVAL(q, datalen, rtnval); - *rlen = datalen + 4; - { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } -} - -/* RID username mapping function. just for fun, it maps to the unix uid */ -static uint32 name_to_rid(char *user_name) -{ - struct passwd *pw = Get_Pwnam(user_name, False); - if (!pw) - { - DEBUG(1,("Username %s is invalid on this system\n", user_name)); - return (uint32)(-1); - } - - return (uint32)(pw->pw_uid); -} - - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -char *dom_sid_to_string(DOM_SID *sid) -{ - static pstring sidstr; - char subauth[16]; - int i; - uint32 ia = (sid->id_auth[0]) + - (sid->id_auth[1] << 8 ) + - (sid->id_auth[2] << 16) + - (sid->id_auth[3] << 24); - - sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); - - for (i = 0; i < sid->num_auths; i++) - { - sprintf(subauth, "-%d", sid->sub_auths[i]); - strcat(sidstr, subauth); - } - - DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); - return sidstr; -} - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -/* identauth >= 2^32 can be detected because it will be specified in hex */ -static void make_dom_sid(DOM_SID *sid, char *domsid) -{ - int identauth; - char *p; - - DEBUG(4,("netlogon domain SID: %s\n", domsid)); - - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - sid->sid_no = atoi(p); - - /* identauth in decimal should be < 2^32 */ - /* identauth in hex should be >= 2^32 */ - identauth = atoi(strtok(0,"-")); - - DEBUG(4,("netlogon rev %d\n", sid->sid_no)); - DEBUG(4,("netlogon %s ia %d\n", p, identauth)); - - sid->id_auth[0] = 0; - sid->id_auth[1] = 0; - sid->id_auth[2] = (identauth & 0xff000000) >> 24; - sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; - sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; - sid->id_auth[5] = (identauth & 0x000000ff); - - sid->num_auths = 0; - - while ((p = strtok(0, "-")) != NULL) - { - sid->sub_auths[sid->num_auths++] = atoi(p); - } -} - -static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) -{ - if (hdr == NULL) return; - - hdr->major = 5; /* RPC version 5 */ - hdr->minor = 0; /* minor version 0 */ - hdr->pkt_type = 2; /* RPC response packet */ - hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ - hdr->frag_len = data_len; /* fragment length, fill in later */ - hdr->auth_len = 0; /* authentication length */ - hdr->call_id = call_id; /* call identifier - match incoming RPC */ - hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ - hdr->context_id = 0; /* presentation context identifier */ - hdr->cancel_count = 0; /* cancel count */ - hdr->reserved = 0; /* reserved */ -} - -static int make_rpc_reply(char *inbuf, char *q, int data_len) -{ - uint32 callid = RIVAL(inbuf, 12); - RPC_HDR hdr; - - create_rpc_reply(&hdr, callid, data_len); - return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q; -} - -static int lsa_reply_open_policy(char *q, char *base) -{ - int i; - LSA_R_OPEN_POL r_o; - - /* set up the LSA QUERY INFO response */ - /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ - for (i = 0; i < POL_HND_SIZE; i++) - { - r_o.pol.data[i] = i; - } - r_o.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) -{ - hdr->uni_max_len = max_len; - hdr->uni_str_len = len; - hdr->undoc = terminate; -} - -static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) -{ - make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); - hdr->undoc_buffer = len > 0 ? 1 : 0; -} - -static void make_unistr(UNISTR *str, char *buf) -{ - /* store the string (null-terminated copy) */ - PutUniCode((char *)(str->buffer), buf); -} - -static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) -{ - /* set up string lengths. add one if string is not null-terminated */ - str->uni_max_len = len + (terminate != 0 ? 1 : 0); - str->undoc = 0; - str->uni_str_len = len; - - /* store the string (null-terminated copy) */ - PutUniCode((char *)str->buffer, buf); - - /* overwrite the last character: some strings are terminated with 4 not 0 */ - str->buffer[len] = (uint16)terminate; -} - -static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) -{ - rid2->type = 0x5; - rid2->undoc = 0x5; - rid2->rid = rid; - rid2->rid_idx = 0; -} - -static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) -{ - int len_sid_str = strlen(sid_str); - - sid2->type = 0x5; - sid2->undoc = 0; - make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); - make_unistr (&(sid2->str), sid_str); -} - -static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) -{ - int domlen = strlen(dom_name); - - d_q->uni_dom_max_len = domlen * 2; - d_q->padding = 0; - d_q->uni_dom_str_len = domlen * 2; - - d_q->buffer_dom_name = 0; /* domain buffer pointer */ - d_q->buffer_dom_sid = 0; /* domain sid pointer */ - - /* NOT null-terminated: 4-terminated instead! */ - make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); - - make_dom_sid(&(d_q->dom_sid), dom_sid); -} - -static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, - char *dom_name, char *dom_sid) -{ - LSA_R_QUERY_INFO r_q; - - /* set up the LSA QUERY INFO response */ - - r_q.undoc_buffer = 1; /* not null */ - r_q.info_class = q_q->info_class; - - make_dom_query(&r_q.dom.id5, dom_name, dom_sid); - - r_q.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_query(False, &r_q, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -/* pretty much hard-coded choice of "other" sids, unfortunately... */ -static void make_dom_ref(DOM_R_REF *ref, - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int len_dom_name = strlen(dom_name); - int len_other_sid1 = strlen(other_sid1); - int len_other_sid2 = strlen(other_sid2); - int len_other_sid3 = strlen(other_sid3); - - ref->undoc_buffer = 1; - ref->num_ref_doms_1 = 4; - ref->buffer_dom_name = 1; - ref->max_entries = 32; - ref->num_ref_doms_2 = 4; - - make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); - make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); - - if (dom_name != NULL) - { - make_unistr(&(ref->uni_dom_name), dom_name); - } - - make_dom_sid(&(ref->ref_dom[0]), dom_sid ); - make_dom_sid(&(ref->ref_dom[1]), other_sid1); - make_dom_sid(&(ref->ref_dom[2]), other_sid2); - make_dom_sid(&(ref->ref_dom[3]), other_sid3); -} - -static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static int lsa_reply_lookup_sids(char *q, char *base, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - LSA_R_LOOKUP_SIDS r_l; - - /* set up the LSA Lookup SIDs response */ - make_reply_lookup_sids(&r_l, num_entries, dom_sids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static int lsa_reply_lookup_rids(char *q, char *base, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - LSA_R_LOOKUP_RIDS r_l; - - /* set up the LSA Lookup RIDs response */ - make_reply_lookup_rids(&r_l, num_entries, dom_rids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, - DOM_CHAL *srv_chal, int status) -{ - DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__)); - memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); - r_c->status = status; -} - -static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, - DOM_CHAL *srv_chal) -{ - LSA_R_REQ_CHAL r_c; - - DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - - /* set up the LSA REQUEST CHALLENGE response */ - make_lsa_r_req_chal(&r_c, srv_chal, 0); - - /* store the response in the SMB stream */ - q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0); - - DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__)); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, - DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) -{ - memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); - memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); - r_a->status = status; -} - -static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, - DOM_CHAL *resp_cred, int status) -{ - LSA_R_AUTH_2 r_a; - - /* set up the LSA AUTH 2 response */ - - make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); - - /* store the response in the SMB stream */ - q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - DOM_CRED *srv_cred, int status) -{ - memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); - r_a->status = status; -} - -static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - DOM_CRED *srv_cred, int status) -{ - LSA_R_SRV_PWSET r_s; - - /* set up the LSA Server Password Set response */ - make_lsa_r_srv_pwset(&r_s, srv_cred, status); - - /* store the response in the SMB stream */ - q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - -static void make_lsa_user_info(LSA_USER_INFO *usr, - - NTTIME *logon_time, - NTTIME *logoff_time, - NTTIME *kickoff_time, - NTTIME *pass_last_set_time, - NTTIME *pass_can_change_time, - NTTIME *pass_must_change_time, - - char *user_name, - char *full_name, - char *logon_script, - char *profile_path, - char *home_dir, - char *dir_drive, - - uint16 logon_count, - uint16 bad_pw_count, - - uint32 user_id, - uint32 group_id, - uint32 num_groups, - DOM_GID *gids, - uint32 user_flgs, - - char sess_key[16], - - char *logon_srv, - char *logon_dom, - - char *dom_sid, - char *other_sids) /* space-delimited set of SIDs */ -{ - /* only cope with one "other" sid, right now. */ - /* need to count the number of space-delimited sids */ - int i; - int num_other_sids = other_sids != NULL ? 1 : 0; - - int len_user_name = strlen(user_name ); - int len_full_name = strlen(full_name ); - int len_logon_script = strlen(logon_script); - int len_profile_path = strlen(profile_path); - int len_home_dir = strlen(home_dir ); - int len_dir_drive = strlen(dir_drive ); - - int len_logon_srv = strlen(logon_srv); - int len_logon_dom = strlen(logon_dom); - - usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ - - usr->logon_time = *logon_time; - usr->logoff_time = *logoff_time; - usr->kickoff_time = *kickoff_time; - usr->pass_last_set_time = *pass_last_set_time; - usr->pass_can_change_time = *pass_can_change_time; - usr->pass_must_change_time = *pass_must_change_time; - - make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); - make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); - make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); - make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); - make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); - make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); - - usr->logon_count = logon_count; - usr->bad_pw_count = bad_pw_count; - - usr->user_id = user_id; - usr->group_id = group_id; - usr->num_groups = num_groups; - usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ - usr->user_flgs = user_flgs; - - if (sess_key != NULL) - { - memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); - } - else - { - bzero(usr->sess_key, sizeof(usr->sess_key)); - } - - make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); - make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); - - usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ - - bzero(usr->padding, sizeof(usr->padding)); - - usr->num_other_sids = num_other_sids; - usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; - - make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); - make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); - make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); - make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); - make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); - make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); - - usr->num_groups2 = num_groups; - for (i = 0; i < num_groups; i++) - { - usr->gids[i] = gids[i]; - } - - make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); - make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); - - make_dom_sid(&(usr->dom_sid), dom_sid); - make_dom_sid(&(usr->other_sids[0]), other_sids); -} - - -static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - DOM_CRED *srv_cred, LSA_USER_INFO *user_info) -{ - LSA_R_SAM_LOGON r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); - - /* store the user information, if there is any. */ - r_s.user = user_info; - r_s.buffer_user = user_info != NULL ? 1 : 0; - r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - - -static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - DOM_CRED *srv_cred, - uint32 status) -{ - LSA_R_SAM_LOGOFF r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); - - r_s.status = status; - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0); - - /* return length of SMB data stored */ - return PTR_DIFF(q, base); -} - - -static void api_lsa_open_policy( char *param, char *data, - char **rdata, int *rdata_len ) -{ - /* we might actually want to decode the query, but it's not necessary */ - /* lsa_io_q_open_policy(...); */ - - /* return a 20 byte policy handle */ - *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata); -} - -static void api_lsa_query_info( char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_QUERY_INFO q_i; - pstring dom_name; - pstring dom_sid; - - /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata, - dom_name, dom_sid); -} - -static void api_lsa_lookup_sids( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int i; - LSA_Q_LOOKUP_SIDS q_l; - pstring dom_name; - pstring dom_sid; - fstring dom_sids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received SIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); - } - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata, - q_l.num_entries, dom_sids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ -} - -static void api_lsa_lookup_names( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int i; - LSA_Q_LOOKUP_RIDS q_l; - pstring dom_name; - pstring dom_sid; - uint32 dom_rids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received RIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - char *user_name = unistr2(q_l.lookup_name[i].str.buffer); - dom_rids[i] = name_to_rid(user_name); - } - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata, - q_l.num_entries, dom_rids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ -} - -BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum = SVAL(data,22); - - int pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - switch (opnum) - { - case LSA_OPENPOLICY: - { - DEBUG(3,("LSA_OPENPOLICY\n")); - api_lsa_open_policy(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_QUERYINFOPOLICY: - { - DEBUG(3,("LSA_QUERYINFOPOLICY\n")); - - api_lsa_query_info(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_ENUMTRUSTDOM: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_ENUMTRUSTDOM\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); /* enumeration context */ - SIVAL(q, 0, 4); /* entries read */ - SIVAL(q, 0, 8); /* trust information */ - - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - - break; - } - - case LSA_CLOSE: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_CLOSE\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - - break; - } - - case LSA_OPENSECRET: - { - char *q = *rdata + 0x18; - DEBUG(3,("LSA_OPENSECRET\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - - break; - } - - case LSA_LOOKUPSIDS: - { - DEBUG(3,("LSA_OPENSECRET\n")); - api_lsa_lookup_sids(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_LOOKUPNAMES: - { - DEBUG(3,("LSA_LOOKUPNAMES\n")); - api_lsa_lookup_names(param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - default: - { - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - break; - } - } - return True; -} - -static BOOL update_dcinfo(int cnum, uint16 vuid, - struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct) -{ - struct smb_passwd *smb_pass; - int i; - - unbecome_user(); - smb_pass = get_smbpwnam(mach_acct); - become_user(cnum, vuid); - - if (smb_pass != NULL) - { - memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw)); - DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw))); - dump_data(5, dc->md4pw, 16); - } - else - { - /* No such machine account. Should error out here, but we'll - print and carry on */ - DEBUG(1,("No account in domain for %s\n", mach_acct)); - return False; - } - - { - char foo[16]; - for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); - DEBUG(4,("pass %s %s\n", mach_acct, foo)); - } - - /* copy the client credentials */ - memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); - memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data)); - - /* create a server challenge for the client */ - /* PAXX: set these to random values. */ - /* lkcl: paul, you mentioned that it doesn't really matter much */ - for (i = 0; i < 8; i++) - { - dc->srv_chal.data[i] = 0xA5; - } - - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), - dc->md4pw, dc->sess_key); - - DEBUG(6,("update_dcinfo: %d\n", __LINE__)); - - return True; -} - -static void api_lsa_req_chal( int cnum, uint16 vuid, - user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_REQ_CHAL q_r; - - fstring mach_acct; - - /* grab the challenge... */ - lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0); - - fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer)); - - strcat(mach_acct, "$"); - - DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); - dump_data(6, q_r.clnt_chal.data, 8); - - update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); - - /* construct reply. return status is always 0x0 */ - *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata, - &(vuser->dc.srv_chal)); - -} - -static void api_lsa_auth_2( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_AUTH_2 q_a; - - DOM_CHAL srv_chal; - UTIME srv_time; - - srv_time.time = 0; - - /* grab the challenge... */ - lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0); - - /* check that the client credentials are valid */ - cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, - &(vuser->dc.srv_cred), srv_time); - - /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); - - /* construct reply. */ - *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, - &srv_chal, 0x0); -} - - -static BOOL deal_with_credentials(user_struct *vuser, - DOM_CRED *clnt_cred, DOM_CRED *srv_cred) -{ - UTIME new_clnt_time; - - /* doesn't matter that server time is 0 */ - srv_cred->timestamp.time = 0; - - /* check that the client credentials are valid */ - if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, - &(vuser->dc.srv_cred), clnt_cred->timestamp)) - { - return False; - } - - /* increment client time by one second */ - new_clnt_time.time = clnt_cred->timestamp.time + 1; - - /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, - &(srv_cred->challenge)); - - /* update the client and server credentials, for use next time... */ - *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); - - return True; -} - -static void api_lsa_srv_pwset( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SRV_PWSET q_a; - - DOM_CRED srv_cred; - - /* grab the challenge and encrypted password ... */ - lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); - - /* construct reply. always indicate failure. nt keeps going... */ - *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, - &srv_cred, - NT_STATUS_WRONG_PASSWORD|0xC000000); -} - - -static void api_lsa_sam_logoff( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SAM_LOGOFF q_l; - - DOM_CRED srv_cred; - - /* grab the challenge... */ - lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred); - - /* construct reply. always indicate success */ - *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata, - &srv_cred, - 0x0); -} - - -static void api_lsa_sam_logon( user_struct *vuser, - char *param, char *data, - char **rdata, int *rdata_len ) -{ - LSA_Q_SAM_LOGON q_l; - LSA_USER_INFO usr_info; - LSA_USER_INFO *p_usr_info = NULL; - - DOM_CRED srv_creds; - - lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0); - - /* checks and updates credentials. creates reply credentials */ - deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds); - - if (vuser != NULL) - { - NTTIME dummy_time; - pstring logon_script; - pstring profile_path; - pstring home_dir; - pstring home_drive; - pstring my_name; - pstring my_workgroup; - pstring dom_sid; - pstring username; - extern pstring myname; - - dummy_time.low = 0xffffffff; - dummy_time.high = 0x7fffffff; - - get_myname(myname, NULL); - - pstrcpy(logon_script, lp_logon_script()); - pstrcpy(profile_path, lp_logon_path ()); - pstrcpy(dom_sid , lp_domainsid ()); - pstrcpy(my_workgroup, lp_workgroup ()); - - pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); - pstrcpy(my_name , myname ); - strupper(my_name); - - pstrcpy(home_drive , "a:" ); - -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - pstrcpy(home_dir , vuser->home_share); -#else - pstrcpy(home_dir , "\\\\%L\\%U"); - standard_sub_basic(home_dir); -#endif - - p_usr_info = &usr_info; - - make_lsa_user_info(p_usr_info, - - &dummy_time, /* logon_time */ - &dummy_time, /* logoff_time */ - &dummy_time, /* kickoff_time */ - &dummy_time, /* pass_last_set_time */ - &dummy_time, /* pass_can_change_time */ - &dummy_time, /* pass_must_change_time */ - - username, /* user_name */ - vuser->real_name, /* full_name */ - logon_script, /* logon_script */ - profile_path, /* profile_path */ - home_dir, /* home_dir */ - home_drive, /* dir_drive */ - - 0, /* logon_count */ - 0, /* bad_pw_count */ - - vuser->uid, /* uint32 user_id */ - vuser->gid, /* uint32 group_id */ - 0, /* uint32 num_groups */ - NULL, /* DOM_GID *gids */ - 0x20, /* uint32 user_flgs */ - - NULL, /* char sess_key[16] */ - - my_name, /* char *logon_srv */ - my_workgroup, /* char *logon_dom */ - - dom_sid, /* char *dom_sid */ - NULL); /* char *other_sids */ - } - - *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, - &srv_creds, p_usr_info); -} - - -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum = SVAL(data,22); - int pkttype = CVAL(data, 2); - - user_struct *vuser; - - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum)); - - if ((vuser = get_valid_user_struct(uid)) == NULL) return False; - - DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif - - switch (opnum) - { - case LSA_REQCHAL: - { - DEBUG(3,("LSA_REQCHAL\n")); - api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_AUTH2: - { - DEBUG(3,("LSA_AUTH2\n")); - api_lsa_auth_2(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SRVPWSET: - { - DEBUG(3,("LSA_SRVPWSET\n")); - api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SAMLOGON: - { - DEBUG(3,("LSA_SAMLOGON\n")); - api_lsa_sam_logon(vuser, param, data, rdata, rdata_len); - make_rpc_reply(data, *rdata, *rdata_len); - break; - } - - case LSA_SAMLOGOFF: - { - DEBUG(3,("LSA_SAMLOGOFF\n")); - api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len); - break; - } - - default: - { - DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum)); - break; - } - } - - return True; -} - -#endif /* NTDOMAIN */ -- cgit From 9d1f45ca6bbdeeef448ccb55e1275c6f9ec59820 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 16:32:43 +0000 Subject: resolving some of the confusion over credentials. --- source/pipenetlog.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index ef5acdc5450..0191d2fa5e5 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -303,6 +303,7 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, for (i = 0; i < 8; i++) { dc->srv_chal.data[i] = 0xA5; + dc->srv_cred.data[i] = 0xA5; } /* from client / server challenges and md4 password, generate sess key */ @@ -347,7 +348,6 @@ static void api_lsa_auth_2( user_struct *vuser, { LSA_Q_AUTH_2 q_a; - DOM_CHAL srv_chal; UTIME srv_time; srv_time.time = 0; @@ -357,14 +357,17 @@ static void api_lsa_auth_2( user_struct *vuser, /* check that the client credentials are valid */ cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, - &(vuser->dc.srv_cred), srv_time); + &(vuser->dc.clnt_cred), srv_time); - /* create server credentials for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal); + /* create server challenge for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &(vuser->dc.srv_chal)); + + /* update the client credentials (copy server challenge) for use next time */ + memcpy(vuser->dc.clnt_cred.data, vuser->dc.srv_chal.data, sizeof(vuser->dc.clnt_cred.data)); - /* construct reply. */ + /* construct reply. */ *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, - &srv_chal, 0x0); + &(vuser->dc.srv_chal), 0x0); } @@ -378,7 +381,7 @@ static BOOL deal_with_credentials(user_struct *vuser, /* check that the client credentials are valid */ if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, - &(vuser->dc.srv_cred), clnt_cred->timestamp)) + &(vuser->dc.clnt_cred), clnt_cred->timestamp)) { return False; } -- cgit From 14f0c2ddb05a690e671efad8c47da9ff1e39c8ce Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 17:11:07 +0000 Subject: put a check around become_user(). doesn't authenticate the user, but doesn't quit the whole pipe, either... --- source/pipenetlog.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 0191d2fa5e5..b4f0db766bf 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -271,7 +271,11 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, unbecome_user(); smb_pass = get_smbpwnam(mach_acct); - become_user(cnum, vuid); + if (!become_user(cnum, vuid)) + { + DEBUG(0,("update_dcinfo: become_user failed\n")); + return False; + } if (smb_pass != NULL) { -- cgit From 717bcd6e3457f355583b4508d1f4edc9a52650df Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 18:11:20 +0000 Subject: lsa_io_r_req_chal() - challenge is not 4-byte aligned after the unicode strings. --- source/lsaparse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/lsaparse.c b/source/lsaparse.c index 69352466f6b..3c18f5b71d5 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -247,7 +247,9 @@ char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int a q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align, depth); /* logon server unicode string */ q = smb_io_unistr2(io, &(q_c->uni_logon_clnt), q, base, align, depth); /* logon client unicode string */ - q = smb_io_chal(io, &(q_c->clnt_chal), q, base, align, depth); /* client challenge */ + + /* client challenge is _not_ aligned after the unicode strings */ + q = smb_io_chal(io, &(q_c->clnt_chal), q, base, 0, depth); /* client challenge */ return q; } -- cgit From 3db1fe79c300f17d087c85c7e768a8d11c0f7661 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 13 Oct 1997 19:37:43 +0000 Subject: another alignment of client challenge: this one in lsa_io_q_auth_2(). there are going to be a few of these... --- source/lsaparse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/lsaparse.c b/source/lsaparse.c index 3c18f5b71d5..aed110f1b45 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -287,7 +287,8 @@ char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align q = align_offset(q, base, align); q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align, depth); /* client identification info */ - q = smb_io_chal (io, &(q_a->clnt_chal), q, base, align, depth); /* client-calculated credentials */ + /* client challenge is _not_ aligned */ + q = smb_io_chal (io, &(q_a->clnt_chal), q, base, 0, depth); /* client-calculated credentials */ q = smb_io_neg_flags(io, &(q_a->clnt_flgs), q, base, align, depth); return q; -- cgit From 08afa51f5c80f3da983781774378bc1646c431d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 14 Oct 1997 00:16:37 +0000 Subject: Added fixes for become_user braindamage. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index 639bc7be0ba..4af37fdc473 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -722,6 +722,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { pstring fname; int fd; + ret = True; *ptok = (share_lock_token)-1; @@ -759,6 +760,14 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + if(fd < 0) + { + DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", + fname, strerror(errno))); + ret = False; + break; + } + /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) @@ -766,7 +775,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", fname, strerror(errno))); close(fd); - return False; + ret = False; + break; } /* @@ -784,12 +794,18 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok gotlock = True; } while(!gotlock); + /* + * We have to come here if any of the above calls fail + * as we don't want to return and leave ourselves running + * as root ! + */ + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { DEBUG(0,("lock_share_entry: Can't become connected user!\n")); close(fd); - return False; + ret = False; } /* We need to change directory back to the connection root. */ if (ChDir(Connections[cnum].connectpath) != 0) @@ -797,12 +813,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", Connections[cnum].connectpath, strerror(errno))); close(fd); - return False; + ret = False; } } *ptok = (share_lock_token)fd; - return True; + return ret; } /******************************************************************* -- cgit From 9fd056c91196746e09f220a15171f3c97791dcce Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 14 Oct 1997 00:36:57 +0000 Subject: Broke my own rule about checking in uncompiled source :-(. Jeremy. --- source/locking/locking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index 4af37fdc473..04c198afeac 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -722,7 +722,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { pstring fname; int fd; - ret = True; + int ret = True; *ptok = (share_lock_token)-1; -- cgit From 366ec4de30c34b30a9c2a0a0525fcfaa1a6f4bee Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 14 Oct 1997 01:53:20 +0000 Subject: Updated to stop problems with become_user. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index b86ef76a2b8..db4990a7263 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -604,6 +604,7 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { pstring fname; int fd; + int ret = True; *ptok = (share_lock_token)-1; @@ -640,6 +641,14 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + if(fd < 0) + { + DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", + fname, strerror(errno))); + ret = False; + break; + } + /* At this point we have an open fd to the share mode file. Lock the first byte exclusively to signify a lock. */ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) @@ -647,7 +656,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", strerror(errno))); close(fd); - return False; + ret = False; + break; } /* @@ -665,25 +675,32 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok gotlock = True; } while(!gotlock); + /* + * We have to come here if any of the above calls fail + * as we don't want to return and leave ourselves running + * as root ! + */ + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { DEBUG(0,("lock_share_entry: Can't become connected user!\n")); close(fd); - return False; + ret = False; } + /* We need to change directory back to the connection root. */ if (ChDir(Connections[cnum].connectpath) != 0) { DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", Connections[cnum].connectpath, strerror(errno))); close(fd); - return False; + ret = False; } } *ptok = (share_lock_token)fd; - return True; + return ret; } /******************************************************************* -- cgit From 0826e4b41b9fcbcdd8ff758c8b5b6da9ca28eb66 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 14 Oct 1997 02:53:58 +0000 Subject: minor fixes to mangling and oplocks entries in man page --- docs/manpages/smb.conf.5 | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 740c0921919..b5fe0fd1a00 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -282,9 +282,9 @@ substitutions and other smb.conf options. .SS NAME MANGLING -Samba supports "name mangling" so that DOS and Windows clients can use -files that don't conform to the 8.3 format. It can also be set to adjust -the case of 8.3 format filenames. +Samba supports "name mangling" so that older DOS and Windows 3 clients +can use files that don't conform to the 8.3 format. It can also be set +to adjust the case of 8.3 format filenames. There are several options that control the way mangling is performed, and they are grouped here rather than listed separately. For the @@ -1206,12 +1206,11 @@ only one accessing the file and it will aggressively cache file data. With some oplock types the client may even cache file open/close operations. This can give enormous performance benefits. -Samba does not support opportunistic locks because they are very -difficult to do under Unix. Samba can fake them, however, by granting -a oplock whenever a client asks for one. This is controlled using the -smb.conf option "fake oplocks". If you set "fake oplocks = yes" then -you are telling the client that it may aggressively cache the file -data. +Samba does not support opportunistic locks in this release. Samba can +fake them, however, by granting a oplock whenever a client asks for +one. This is controlled using the smb.conf option "fake oplocks". If +you set "fake oplocks = yes" then you are telling the client that it +may aggressively cache the file data. By enabling this option on all read-only shares or shares that you know will only be accessed from one client at a time you will see a big -- cgit From 78348cb8f8afe6454bd0e3a9f0b93b8c9c0b85b9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 14 Oct 1997 09:15:58 +0000 Subject: add become_root()/unbecome_root() calls. These should be used around regions of the code that need root privilages but which normally don't have them (ie. when processing most SMBs). These functions can optionally save/restore the current working directory as well updated several places in the code that previously used unbecome_user() to achieve the same thing to now use become_root() and unbecome_root() changed close_file() to take an additional argument which says whether this is a normal SMBclose type call or a close that resulted from some other action, such as the close of a connection. If it is a abnormal close then don't use magic scripts or print files. changed sys_utime() to ignore any attempt to set the modification time to 0 or -1. We've had reports that files have had their time set to 0 so this should catch those. --- source/include/proto.h | 4 ++- source/lib/system.c | 13 ++++++-- source/locking/locking.c | 65 ++++++++++++------------------------- source/smbd/ipc.c | 5 ++- source/smbd/pipes.c | 4 +-- source/smbd/reply.c | 24 +++++++------- source/smbd/server.c | 23 ++++++++----- source/smbd/trans2.c | 4 +-- source/smbd/uid.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 152 insertions(+), 74 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index ffa2f251cca..d7cbc4cc4c4 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -705,7 +705,7 @@ int fd_attempt_open(char *fname, int flags, int mode); void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr); int fd_attempt_close(file_fd_struct *fd_ptr); void sync_file(int fnum); -void close_file(int fnum); +void close_file(int fnum, int normal_close); BOOL check_file_sharing(int cnum,char *fname); void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int mode,int *Access,int *action); @@ -847,6 +847,8 @@ BOOL become_guest(void); BOOL become_user(int cnum, uint16 vuid); BOOL unbecome_user(void ); int smbrun(char *cmd,char *outfile,BOOL shared); +void become_root(int save_dir) ; +void unbecome_root(int restore_dir); /*The following definitions come from username.c */ diff --git a/source/lib/system.c b/source/lib/system.c index df24691512f..b149ccb4b98 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -194,14 +194,23 @@ now for utime() ********************************************************************/ int sys_utime(char *fname,struct utimbuf *times) { - return(utime(dos_to_unix(fname,False),times)); + /* if the modtime is 0 or -1 then ignore the call and + return success */ + if (times->modtime == (time_t)0 || times->modtime == (time_t)-1) + return 0; + + /* if the access time is 0 or -1 then set it to the modtime */ + if (times->actime == (time_t)0 || times->actime == (time_t)-1) + times->actime = times->modtime; + + return(utime(dos_to_unix(fname,False),times)); } + /********************************************************* for rename across filesystems Patch from Warren Birnbaum <warrenb@hpcvscdp.cv.hp.com> **********************************************************/ - static int copy_reg (const char *source, const char *dest) { diff --git a/source/locking/locking.c b/source/locking/locking.c index db4990a7263..461ad5aef0b 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -611,10 +611,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok if(!share_name(cnum, dev, inode, fname)) return False; + /* we need to do this as root */ + become_root(0); + { int old_umask; BOOL gotlock = False; - unbecome_user(); old_umask = umask(0); /* @@ -675,31 +677,14 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok gotlock = True; } while(!gotlock); - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - umask(old_umask); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("lock_share_entry: Can't become connected user!\n")); - close(fd); - ret = False; - } - - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - close(fd); - ret = False; - } } *ptok = (share_lock_token)fd; + + /* return to our previous privilage level */ + unbecome_root(0); + return ret; } @@ -727,31 +712,21 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok /******************************************************************* Force a share file to be deleted. ********************************************************************/ - static int delete_share_file( int cnum, char *fname ) { - unbecome_user(); - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("delete_share_file: Can't become connected user!\n")); - return -1; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - return -1; - } - return 0; + /* the share file could be owned by anyone, so do this as root */ + become_root(0); + + if(unlink(fname) != 0) { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } else { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + unbecome_root(0); + + return 0; } /******************************************************************* diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index a0a4ec8fc73..1d7ee375d3f 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1601,13 +1601,14 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, name[l] = 0; DEBUG(3,("Setting print name to %s\n",name)); + + become_root(1); for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].open && Files[i].print_file) { pstring wd; GetWd(wd); - unbecome_user(); if (!become_user(Files[i].cnum,vuid) || !become_service(Files[i].cnum,True)) @@ -1617,6 +1618,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, string_set(&Files[i].name,name); break; } + + unbecome_root(1); } desc.errcode=NERR_Success; diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index feb8d91a5b0..2cc6eea506f 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -141,7 +141,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -149,7 +149,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 7925add45f3..ffa80aac870 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -1138,7 +1138,7 @@ int reply_open(char *inbuf,char *outbuf) } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1148,7 +1148,7 @@ int reply_open(char *inbuf,char *outbuf) if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1229,7 +1229,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1237,7 +1237,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1277,7 +1277,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) int i; for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].uid == vuser->uid && Files[i].open) { - close_file(i); + close_file(i, 0); } } @@ -2190,7 +2190,7 @@ int reply_close(char *inbuf,char *outbuf) /* try and set the date */ set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum, 1); /* We have a cached error */ if(eclass || err) @@ -2237,7 +2237,7 @@ int reply_writeclose(char *inbuf,char *outbuf) set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum, 1); DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, @@ -2468,7 +2468,7 @@ int reply_printclose(char *inbuf,char *outbuf) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - close_file(fnum); + close_file(fnum, 1); DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); @@ -3040,14 +3040,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum2 = find_free_file(); if (fnum2<0) { - close_file(fnum1); + close_file(fnum1, 0); return(False); } open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, ofun,st.st_mode,&Access,&action); if (!Files[fnum2].open) { - close_file(fnum1); + close_file(fnum1, 0); return(False); } @@ -3058,8 +3058,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, if (st.st_size) ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); - close_file(fnum1); - close_file(fnum2); + close_file(fnum1, 0); + close_file(fnum2, 0); return(ret == st.st_size); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 8e1bc152ffd..3bfd5bbbf40 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1348,8 +1348,13 @@ static void check_magic(int fnum,int cnum) /**************************************************************************** close a file - possibly invalidating the read prediction + +If normal_close is 1 then this came from a normal SMBclose (or equivalent) +operation otherwise it came as the result of some other operation such as +the closing of the connection. In the latter case printing and +magic scripts are not run ****************************************************************************/ -void close_file(int fnum) +void close_file(int fnum, int normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; @@ -1386,11 +1391,12 @@ void close_file(int fnum) unlock_share_entry( cnum, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (fs_p->print_file) + if (normal_close && fs_p->print_file) print_file(fnum); /* check for magic scripts */ - check_magic(fnum,cnum); + if (normal_close) + check_magic(fnum,cnum); DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, @@ -1510,7 +1516,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, if (*share_locked && lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, Files[fnum].fd_ptr->inode, token); - close_file(fnum); + close_file(fnum, 0); /* Share mode no longer locked. */ *share_locked = False; errno = EACCES; @@ -3203,7 +3209,7 @@ static void close_open_files(int cnum) int i; for (i=0;i<MAX_OPEN_FILES;i++) if( Files[i].cnum == cnum && Files[i].open) { - close_file(i); + close_file(i, 0); } } @@ -3216,6 +3222,10 @@ void close_cnum(int cnum, uint16 vuid) { DirCacheFlush(SNUM(cnum)); + close_open_files(cnum); + dptr_closecnum(cnum); + + /* after this we are running as root, so be careful! */ unbecome_user(); if (!OPEN_CNUM(cnum)) @@ -3236,9 +3246,6 @@ void close_cnum(int cnum, uint16 vuid) if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - close_open_files(cnum); - dptr_closecnum(cnum); - /* execute any "postexec = " line */ if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid)) { diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index ecc8f5dbec7..f7351b99e5a 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -226,7 +226,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -235,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source/smbd/uid.c b/source/smbd/uid.c index cdc4e474c61..fe2cb5a652d 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -258,6 +258,8 @@ BOOL become_user(int cnum, uint16 vuid) if (current_user.ngroups > 0) if (setgroups(current_user.ngroups,current_user.groups)<0) DEBUG(0,("setgroups call failed!\n")); + } else { + current_user.ngroups = 0; } #endif @@ -318,7 +320,8 @@ BOOL unbecome_user(void ) current_user.uid = initial_uid; current_user.gid = initial_gid; - + current_user.ngroups = 0; + if (ChDir(OriginalDir) != 0) DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", timestring(),OriginalDir)); @@ -476,3 +479,82 @@ int smbrun(char *cmd,char *outfile,BOOL shared) #endif return 1; } + + + +static struct current_user current_user_saved; +static int become_root_depth; +static pstring become_root_dir; + +/**************************************************************************** +This is used when we need to do a privilaged operation (such as mucking +with share mode files) and temporarily need root access to do it. This +call should always be paired with an unbecome_root() call immediately +after the operation + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void become_root(int save_dir) +{ + if (become_root_depth) { + DEBUG(0,("ERROR: become root depth is non zero\n")); + } + if (save_dir) + GetWd(become_root_dir); + + current_user_saved = current_user; + become_root_depth = 1; + + become_gid(0); + become_uid(0); +} + +/**************************************************************************** +When the privilaged operation is over call this + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void unbecome_root(int restore_dir) +{ + if (become_root_depth != 1) { + DEBUG(0,("ERROR: unbecome root depth is %d\n", + become_root_depth)); + } + + /* we might have done a become_user() while running as root, + if we have then become root again in order to become + non root! */ + if (current_user.uid != 0) { + become_uid(0); + } + + /* restore our gid first */ + if (!become_gid(current_user_saved.gid)) { + DEBUG(0,("ERROR: Failed to restore gid\n")); + exit_server("Failed to restore gid"); + } + +#ifndef NO_SETGROUPS + if (current_user_saved.ngroups > 0) { + if (setgroups(current_user_saved.ngroups, + current_user_saved.groups)<0) + DEBUG(0,("ERROR: setgroups call failed!\n")); + } +#endif + + /* now restore our uid */ + if (!become_uid(current_user_saved.uid)) { + DEBUG(0,("ERROR: Failed to restore uid\n")); + exit_server("Failed to restore uid"); + } + + if (restore_dir) + ChDir(become_root_dir); + + current_user = current_user_saved; + + become_root_depth = 0; +} + + + -- cgit From 0056b154435e9d2a3fd2be37f7c3afd9e3fbfd87 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 14 Oct 1997 10:17:12 +0000 Subject: changed *(uint32*)(clnt_cred) to SIVAL(clnt_cred, ....) --- source/pipenetlog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index b4f0db766bf..861bae3809b 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -379,6 +379,7 @@ static BOOL deal_with_credentials(user_struct *vuser, DOM_CRED *clnt_cred, DOM_CRED *srv_cred) { UTIME new_clnt_time; + uint32 new_cred; /* doesn't matter that server time is 0 */ srv_cred->timestamp.time = 0; @@ -398,7 +399,9 @@ static BOOL deal_with_credentials(user_struct *vuser, &(srv_cred->challenge)); /* update the client and server credentials, for use next time... */ - *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time ); + new_cred = IVAL(vuser->dc.clnt_cred.data, 0) + new_clnt_time.time; + SIVAL(vuser->dc.clnt_cred.data, new_cred, 0); + SIVAL(vuser->dc.srv_cred.data , new_cred, 0); return True; } -- cgit From 1f9eb492023de95f8f7cabc2c4cafcf2170d43a8 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Tue, 14 Oct 1997 13:12:01 +0000 Subject: docs/DIAGNOSIS.txt: Added comment right up front about "your server is being unfriendly" type error messages. source/Makefile: Added compile options for RedHat Linux 5.0 series. --- docs/textdocs/DIAGNOSIS.txt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/textdocs/DIAGNOSIS.txt b/docs/textdocs/DIAGNOSIS.txt index 11eb91b2ff8..18259ecc94f 100644 --- a/docs/textdocs/DIAGNOSIS.txt +++ b/docs/textdocs/DIAGNOSIS.txt @@ -1,5 +1,5 @@ Contributor: Andrew Tridgell -Updated: June 27, 1997 +Updated: October 14, 1997 Subject: DIAGNOSING YOUR SAMBA SERVER =========================================================================== @@ -44,6 +44,15 @@ smb.conf. I will assume this share is called "tmp". You can add a THESE TESTS ASSUME VERSION 1.9.16 OR LATER OF THE SAMBA SUITE. SOME COMMANDS SHOWN DID NOT EXIST IN EARLIER VERSIONS +Please pay attention to the error messages you receive. If any error message +reports that your server is being unfriendly you should first check that you +IP name resolution is correctly set up. eg: Make sure your /etc/resolv.conf +file points to name servers that really do exist. + +Also, if you do not have DNS server access for name resolution please check +that the settings for your smb.conf file results in "dns proxy = no". The +best way to check this is with "testparm smb.conf" + TEST 1: ------- @@ -53,7 +62,7 @@ In the directory in which you store your smb.conf file, run the command configuration file is faulty. Note: Your smb.conf file may be located in: /etc - or in: /usr/local/samba/lib + Or in: /usr/local/samba/lib TEST 2: @@ -254,7 +263,10 @@ Still having troubles? ---------------------- Try the mailing list or newsgroup, or use the tcpdump-smb utility to -sniff the problem. +sniff the problem. The official samba mailing list can be reached at +samba@samba.anu.edu.au. To find out more about samba and how to +subscribe to the mailing list check out the samba web page at + http://samba.anu.edu.au/samba Also look at the other docs in the Samba package! -- cgit From 676c443d21ff8f5e659e933ee3e22cd0e79c50f3 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Tue, 14 Oct 1997 13:18:07 +0000 Subject: docs/DIAGNOSIS.txt: Added comments up front about "your server is being unfriendly" and need to check IP name resolution. --- docs/textdocs/DIAGNOSIS.txt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/textdocs/DIAGNOSIS.txt b/docs/textdocs/DIAGNOSIS.txt index 11eb91b2ff8..18259ecc94f 100644 --- a/docs/textdocs/DIAGNOSIS.txt +++ b/docs/textdocs/DIAGNOSIS.txt @@ -1,5 +1,5 @@ Contributor: Andrew Tridgell -Updated: June 27, 1997 +Updated: October 14, 1997 Subject: DIAGNOSING YOUR SAMBA SERVER =========================================================================== @@ -44,6 +44,15 @@ smb.conf. I will assume this share is called "tmp". You can add a THESE TESTS ASSUME VERSION 1.9.16 OR LATER OF THE SAMBA SUITE. SOME COMMANDS SHOWN DID NOT EXIST IN EARLIER VERSIONS +Please pay attention to the error messages you receive. If any error message +reports that your server is being unfriendly you should first check that you +IP name resolution is correctly set up. eg: Make sure your /etc/resolv.conf +file points to name servers that really do exist. + +Also, if you do not have DNS server access for name resolution please check +that the settings for your smb.conf file results in "dns proxy = no". The +best way to check this is with "testparm smb.conf" + TEST 1: ------- @@ -53,7 +62,7 @@ In the directory in which you store your smb.conf file, run the command configuration file is faulty. Note: Your smb.conf file may be located in: /etc - or in: /usr/local/samba/lib + Or in: /usr/local/samba/lib TEST 2: @@ -254,7 +263,10 @@ Still having troubles? ---------------------- Try the mailing list or newsgroup, or use the tcpdump-smb utility to -sniff the problem. +sniff the problem. The official samba mailing list can be reached at +samba@samba.anu.edu.au. To find out more about samba and how to +subscribe to the mailing list check out the samba web page at + http://samba.anu.edu.au/samba Also look at the other docs in the Samba package! -- cgit From 9b095887df204393090d7da9a47508685ddd5163 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 14 Oct 1997 17:01:43 +0000 Subject: credentials, query info reply. --- source/include/byteorder.h | 4 +-- source/include/proto.h | 8 +++--- source/include/smb.h | 7 ++--- source/libsmb/credentials.c | 68 +++++++++++++++++++++------------------------ source/pipenetlog.c | 39 +++++++++++++------------- source/pipentlsa.c | 9 +++--- source/pipeutil.c | 7 ++--- source/smbparse.c | 8 ++++-- 8 files changed, 72 insertions(+), 78 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index a6f826b518d..06337b91a2b 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -220,10 +220,10 @@ it also defines lots of intermediate macros, just ignore those :-) #define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \ RW_SVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s%04x %s: %04x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *((uint16*)(inbuf)))); #define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \ RW_IVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s%04x %s: %08x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *((uint32*)(inbuf)))); diff --git a/source/include/proto.h b/source/include/proto.h index 324431e2b3d..ca60239412f 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -63,10 +63,10 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind); /*The following definitions come from credentials.c */ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, - char *session_key); -void cred_create(char *session_key, DOM_CHAL *stored_cred, UTIME timestamp, + uint32 session_key[2]); +void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, DOM_CHAL *cred); -int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, +int cred_assert(DOM_CHAL *cred, uint32 session_key[2], DOM_CHAL *stored_cred, UTIME timestamp); /*The following definitions come from dir.c */ @@ -665,7 +665,7 @@ int make_rpc_reply(char *inbuf, char *q, int data_len); void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate); void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate); void make_unistr(UNISTR *str, char *buf); -void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate); +void make_unistr2(UNISTR2 *str, char *buf, int len); void make_dom_rid2(DOM_RID2 *rid2, uint32 rid); void make_dom_sid2(DOM_SID2 *sid2, char *sid_str); diff --git a/source/include/smb.h b/source/include/smb.h index 58dfc141bd4..8e34b063596 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -394,7 +394,7 @@ typedef struct log_info /* DOM_CHAL - challenge info */ typedef struct chal_info { - uint8 data[8]; /* credentials */ + uint32 data[2]; /* credentials */ } DOM_CHAL; @@ -492,7 +492,6 @@ typedef struct rpc_hdr_info typedef struct dom_query_info { uint16 uni_dom_max_len; /* domain name string length * 2 */ - uint16 padding; /* 2 padding bytes? */ uint16 uni_dom_str_len; /* domain name string length * 2 */ uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ @@ -1018,8 +1017,8 @@ struct dcinfo DOM_CHAL clnt_cred; /* Last client credential */ DOM_CHAL srv_cred; /* Last server credential */ - char sess_key[8]; /* Session key */ - uchar md4pw[16]; /* md4(machine password) */ + uint32 sess_key[2]; /* Session key */ + uchar md4pw[16]; /* md4(machine password) */ }; typedef struct diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index 3355ab17040..07816bc0cf2 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -31,11 +31,12 @@ Output: 8 byte session key ****************************************************************************/ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, - char *session_key) + uint32 session_key[2]) { uint32 sum[2]; char sum2[8]; char buf[8]; + char netsesskey[8]; sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); @@ -44,22 +45,18 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, SIVAL(sum2,4,sum[1]); smbhash(pass , sum2, buf); - smbhash(pass+9, buf , session_key); + smbhash(pass+9, buf , netsesskey); - /* debug output*/ - DEBUG(4,("cred_session_key\n")); - - DEBUG(5,(" clnt_chal: ")); - dump_data(5, clnt_chal->data, 8); + session_key[0] = IVAL(netsesskey, 0); + session_key[1] = IVAL(netsesskey, 4); - DEBUG(5,(" srv_chal: ")); - dump_data(5, srv_chal->data, 8); - - DEBUG(5,(" clnt_chal+srv_chal: ")); - dump_data(5, sum2, 8); + /* debug output */ + DEBUG(4,("cred_session_key\n")); - DEBUG(5,(" session_key: ")); - dump_data(5, session_key, 16); + DEBUG(5,(" clnt_chal: %lx %lx\n", clnt_chal->data[0], clnt_chal->data[1])); + DEBUG(5,(" srv_chal : %lx %lx\n", srv_chal ->data[0], srv_chal ->data[1])); + DEBUG(5,(" clnt+srv : %lx %lx\n", sum [0], sum [1])); + DEBUG(5,(" sess_key : %lx %lx\n", session_key [0], session_key [1])); } @@ -74,35 +71,36 @@ Input: Output: 8 byte credential ****************************************************************************/ -void cred_create(char *session_key, DOM_CHAL *stored_cred, UTIME timestamp, +void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, DOM_CHAL *cred) { char key2[7]; char buf[8]; + char calc_cred[8]; char timecred[8]; + char netsesskey[8]; + + SIVAL(netsesskey, 0, session_key[0]); + SIVAL(netsesskey, 4, session_key[1]); - memcpy(timecred, stored_cred->data, 8); - SIVAL(timecred, 0, IVAL(stored_cred, 0) + timestamp.time); + SIVAL(timecred, 0, IVAL(stor_cred, 0) + timestamp.time); + SIVAL(timecred, 4, IVAL(stor_cred, 4)); - smbhash(session_key, timecred, buf); + smbhash(netsesskey, timecred, buf); memset(key2, 0, 7); - key2[0] = session_key[7]; - smbhash(key2, buf, cred->data); + key2[0] = netsesskey[7]; + smbhash(key2, buf, calc_cred); + + cred->data[0] = IVAL(calc_cred, 0); + cred->data[1] = IVAL(calc_cred, 4); /* debug output*/ DEBUG(4,("cred_create\n")); - DEBUG(5,(" session_key: ")); - dump_data(5, session_key, 16); - - DEBUG(5,(" stored_cred: ")); - dump_data(5, stored_cred->data, 8); - - DEBUG(5,(" timecred: ")); - dump_data(5, timecred, 8); - - DEBUG(5,(" cred: ")); - dump_data(5, cred->data, 8); + DEBUG(5,(" sess_key : %lx %lx\n", session_key [0], session_key [1])); + DEBUG(5,(" stor_cred: %lx %lx\n", stor_cred->data[0], stor_cred->data[1])); + DEBUG(5,(" timecred : %lx %lx\n", IVAL(timecred, 0), IVAL(timecred, 4))); + DEBUG(5,(" calc_cred: %lx %lx\n", cred ->data[0], cred ->data[1])); } @@ -119,7 +117,7 @@ Output: returns 1 if computed credential matches received credential returns 0 otherwise ****************************************************************************/ -int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, +int cred_assert(DOM_CHAL *cred, uint32 session_key[2], DOM_CHAL *stored_cred, UTIME timestamp) { DOM_CHAL cred2; @@ -129,11 +127,9 @@ int cred_assert(DOM_CHAL *cred, char *session_key, DOM_CHAL *stored_cred, /* debug output*/ DEBUG(4,("cred_assert\n")); + DEBUG(5,(" challenge : %lx %lx\n", cred->data[0], cred->data[1])); + DEBUG(5,(" calculated: %lx %lx\n", cred2.data[0], cred2.data[1])); DEBUG(5,(" challenge: ")); - dump_data(5, cred->data, 8); - - DEBUG(5,(" calculated: ")); - dump_data(5, cred2.data, 8); return memcmp(cred->data, cred2.data, 8) == 0; } diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 861bae3809b..acb7f806b94 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -200,12 +200,12 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, usr->num_other_sids = num_other_sids; usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; - make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); - make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); - make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); - make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); - make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); - make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name ); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name ); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir ); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive ); usr->num_groups2 = num_groups; for (i = 0; i < num_groups; i++) @@ -213,8 +213,8 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, usr->gids[i] = gids[i]; } - make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); - make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); + make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv); + make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom); make_dom_sid(&(usr->dom_sid), dom_sid); make_dom_sid(&(usr->other_sids[0]), other_sids); @@ -304,11 +304,10 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, /* create a server challenge for the client */ /* PAXX: set these to random values. */ /* lkcl: paul, you mentioned that it doesn't really matter much */ - for (i = 0; i < 8; i++) - { - dc->srv_chal.data[i] = 0xA5; - dc->srv_cred.data[i] = 0xA5; - } + dc->srv_chal.data[0] = 0x11111111; + dc->srv_chal.data[1] = 0x11111111; + dc->srv_cred.data[0] = 0x11111111; + dc->srv_cred.data[1] = 0x11111111; /* from client / server challenges and md4 password, generate sess key */ cred_session_key(&(dc->clnt_chal), &(dc->srv_chal), @@ -335,8 +334,8 @@ static void api_lsa_req_chal( int cnum, uint16 vuid, strcat(mach_acct, "$"); - DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data))); - dump_data(6, q_r.clnt_chal.data, 8); + DEBUG(6,("q_r.clnt_chal.data: %lx %lx\n", + q_r.clnt_chal.data[0], q_r.clnt_chal.data[1])); update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct); @@ -352,6 +351,7 @@ static void api_lsa_auth_2( user_struct *vuser, { LSA_Q_AUTH_2 q_a; + DOM_CHAL srv_cred; UTIME srv_time; srv_time.time = 0; @@ -364,14 +364,15 @@ static void api_lsa_auth_2( user_struct *vuser, &(vuser->dc.clnt_cred), srv_time); /* create server challenge for inclusion in the reply */ - cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &(vuser->dc.srv_chal)); + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_cred); - /* update the client credentials (copy server challenge) for use next time */ - memcpy(vuser->dc.clnt_cred.data, vuser->dc.srv_chal.data, sizeof(vuser->dc.clnt_cred.data)); + /* update the client credentials for use next time */ + memcpy(vuser->dc.clnt_cred.data, &(srv_cred.data), sizeof(srv_cred.data)); + memcpy(vuser->dc.srv_cred .data, &(srv_cred.data), sizeof(srv_cred.data)); /* construct reply. */ *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, - &(vuser->dc.srv_chal), 0x0); + &srv_cred, 0x0); } diff --git a/source/pipentlsa.c b/source/pipentlsa.c index 55deffabd6f..9a57b6df9b7 100644 --- a/source/pipentlsa.c +++ b/source/pipentlsa.c @@ -59,14 +59,13 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) int domlen = strlen(dom_name); d_q->uni_dom_max_len = domlen * 2; - d_q->padding = 0; d_q->uni_dom_str_len = domlen * 2; - d_q->buffer_dom_name = 0; /* domain buffer pointer */ - d_q->buffer_dom_sid = 0; /* domain sid pointer */ + d_q->buffer_dom_name = 1; /* domain buffer pointer */ + d_q->buffer_dom_sid = 1; /* domain sid pointer */ - /* NOT null-terminated: 4-terminated instead! */ - make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); + /* this string is supposed to be character short */ + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen); make_dom_sid(&(d_q->dom_sid), dom_sid); } diff --git a/source/pipeutil.c b/source/pipeutil.c index ce3f1535c4c..b9201f3c958 100644 --- a/source/pipeutil.c +++ b/source/pipeutil.c @@ -180,18 +180,15 @@ void make_unistr(UNISTR *str, char *buf) PutUniCode((char *)(str->buffer), buf); } -void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) +void make_unistr2(UNISTR2 *str, char *buf, int len) { /* set up string lengths. add one if string is not null-terminated */ - str->uni_max_len = len + (terminate != 0 ? 1 : 0); + str->uni_max_len = len; str->undoc = 0; str->uni_str_len = len; /* store the string (null-terminated copy) */ PutUniCode((char *)str->buffer, buf); - - /* overwrite the last character: some strings are terminated with 4 not 0 */ - str->buffer[len] = (uint16)terminate; } void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) diff --git a/source/smbparse.c b/source/smbparse.c index ba3e073e5fb..39200f53516 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -73,6 +73,7 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int q = align_offset(q, base, align); + DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; DBG_RW_CVAL("sid_no ", depth, base, io, q, sid->sid_no); q++; DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; @@ -279,8 +280,11 @@ char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int d q = align_offset(q, base, align); + DBG_RW_IVAL("data[0]", depth, base, io, q, chal->data[0]); q += 4; + DBG_RW_IVAL("data[1]", depth, base, io, q, chal->data[1]); q += 4; +/* DBG_RW_PCVAL("data", depth, base, io, q, chal->data, 8); q += 8; - +*/ return q; } @@ -510,9 +514,7 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, q = align_offset(q, base, align); - DBG_RW_SVAL("uni_dom_max_len", depth, base, io, q, d_q->uni_dom_max_len); q += 2; /* domain name string length * 2 */ - DBG_RW_SVAL("padding ", depth, base, io, q, d_q->padding ); q += 2; /* 2 padding bytes */ DBG_RW_SVAL("uni_dom_str_len", depth, base, io, q, d_q->uni_dom_str_len); q += 2; /* domain name string length * 2 */ DBG_RW_IVAL("buffer_dom_name", depth, base, io, q, d_q->buffer_dom_name); q += 4; /* undocumented domain name string buffer pointer */ -- cgit From eafd6e9e797c5badb07059d7eddabd6a8947c830 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 14 Oct 1997 18:37:55 +0000 Subject: byteorder.h: created a RW_PIVAL macro which was missing. smbparse.c: smb_io_dom_sid() was storing its sub-authorities as uint16s instead of uint32s. used the DBG_RW_PIVAL macro instead of DBG_RW_PSVAL. pipentlsa.c: not sure. something to do with the Query Info reply. pipeutil.c: make_rpc_reply() had the packed representation field set to 0x0100 0000 instead of 0x1000 0000, which had the interesting result of turning all uint32 and uint16 field byte ordering the other way round! --- source/include/byteorder.h | 15 +++++++++++++-- source/pipentlsa.c | 6 +++--- source/pipeutil.c | 4 ++-- source/smbparse.c | 6 ++---- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index 06337b91a2b..e11771c3abe 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -94,6 +94,10 @@ it also defines lots of intermediate macros, just ignore those :-) if (read) { PCVAL (inbuf,0,outbuf,len) } \ else { PSCVAL(inbuf,0,outbuf,len) } +#define RW_PIVAL(read,inbuf,outbuf,len) \ + if (read) { PIVAL (inbuf,0,outbuf,len) } \ + else { PSIVAL(inbuf,0,outbuf,len) } + #define RW_PSVAL(read,inbuf,outbuf,len) \ if (read) { PSVAL (inbuf,0,outbuf,len) } \ else { PSSVAL(inbuf,0,outbuf,len) } @@ -202,14 +206,21 @@ it also defines lots of intermediate macros, just ignore those :-) RW_PCVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%x ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_PSVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PSVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); + +#define DBG_RW_PIVAL(string,depth,base,read,inbuf,outbuf,len) \ + RW_PIVAL(read,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \ DEBUG(5,("\n")); #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ diff --git a/source/pipentlsa.c b/source/pipentlsa.c index 9a57b6df9b7..030e00e87ab 100644 --- a/source/pipentlsa.c +++ b/source/pipentlsa.c @@ -61,8 +61,8 @@ static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) d_q->uni_dom_max_len = domlen * 2; d_q->uni_dom_str_len = domlen * 2; - d_q->buffer_dom_name = 1; /* domain buffer pointer */ - d_q->buffer_dom_sid = 1; /* domain sid pointer */ + d_q->buffer_dom_name = 4; /* domain buffer pointer */ + d_q->buffer_dom_sid = 2; /* domain sid pointer */ /* this string is supposed to be character short */ make_unistr2(&(d_q->uni_domain_name), dom_name, domlen); @@ -77,7 +77,7 @@ static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, /* set up the LSA QUERY INFO response */ - r_q.undoc_buffer = 1; /* not null */ + r_q.undoc_buffer = 0x22000000; /* bizarre */ r_q.info_class = q_q->info_class; make_dom_query(&r_q.dom.id5, dom_name, dom_sid); diff --git a/source/pipeutil.c b/source/pipeutil.c index b9201f3c958..f55a8d2181e 100644 --- a/source/pipeutil.c +++ b/source/pipeutil.c @@ -142,7 +142,7 @@ void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) hdr->minor = 0; /* minor version 0 */ hdr->pkt_type = 2; /* RPC response packet */ hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ + hdr->pack_type = 0x10; /* packed data representation */ hdr->frag_len = data_len; /* fragment length, fill in later */ hdr->auth_len = 0; /* authentication length */ hdr->call_id = call_id; /* call identifier - match incoming RPC */ @@ -154,7 +154,7 @@ void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) int make_rpc_reply(char *inbuf, char *q, int data_len) { - uint32 callid = RIVAL(inbuf, 12); + uint32 callid = IVAL(inbuf, 12); RPC_HDR hdr; create_rpc_reply(&hdr, callid, data_len); diff --git a/source/smbparse.c b/source/smbparse.c index 39200f53516..855d46420a7 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -71,9 +71,7 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int DEBUG(5,("%s%04x smb_io_dom_sid\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; - q = align_offset(q, base, align); - - DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; + DBG_RW_IVAL("num_auths ", depth, base, io, q, sid->num_auths); q += 4; DBG_RW_CVAL("sid_no ", depth, base, io, q, sid->sid_no); q++; DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; @@ -87,7 +85,7 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int /* oops! XXXX should really issue a warning here... */ if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; - DBG_RW_PSVAL("num_auths ", depth, base, io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; + DBG_RW_PIVAL("num_auths ", depth, base, io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 4; return q; } -- cgit From 28de393878872081bac3a0b3ca82d915eae56701 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Tue, 14 Oct 1997 19:30:07 +0000 Subject: Added a copy of the LGPL to the samba/ubiqx/ directory. --- source/ubiqx/COPYING | 481 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 source/ubiqx/COPYING diff --git a/source/ubiqx/COPYING b/source/ubiqx/COPYING new file mode 100644 index 00000000000..8c8377da464 --- /dev/null +++ b/source/ubiqx/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! -- cgit From 93879ac8a533ad8cc175275cf1fc9a8f152f4b5a Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Tue, 14 Oct 1997 19:31:07 +0000 Subject: pipentlsa.c : lsa close odd bug. smbparse.c : smb_io_dom_sid() _does_ need 4-byte alignment before it. --- source/pipentlsa.c | 22 ++++++++++++++-------- source/smbparse.c | 2 ++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/source/pipentlsa.c b/source/pipentlsa.c index 030e00e87ab..d27b7b2b763 100644 --- a/source/pipentlsa.c +++ b/source/pipentlsa.c @@ -40,8 +40,8 @@ static int lsa_reply_open_policy(char *q, char *base) LSA_R_OPEN_POL r_o; /* set up the LSA QUERY INFO response */ - /* bzero(&(r_o.pol.data), POL_HND_SIZE); */ - for (i = 0; i < POL_HND_SIZE; i++) + bzero(&(r_o.pol.data), POL_HND_SIZE); + for (i = 4; i < POL_HND_SIZE; i++) { r_o.pol.data[i] = i; } @@ -337,6 +337,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, SIVAL(q, 0, 4); /* entries read */ SIVAL(q, 0, 8); /* trust information */ + q += 12; + endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); break; @@ -344,17 +346,19 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, case LSA_CLOSE: { - char *q = *rdata + 0x18; + char *q; DEBUG(3,("LSA_CLOSE\n")); initrpcreply(data, *rdata); - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); + q = *rdata + 0x18; + + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); @@ -374,6 +378,8 @@ BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, SIVAL(q, 0, 12); SIVAL(q, 0, 16); + q += 20; + endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); break; diff --git a/source/smbparse.c b/source/smbparse.c index 855d46420a7..64a0e640cb2 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -71,6 +71,8 @@ char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int DEBUG(5,("%s%04x smb_io_dom_sid\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; + q = align_offset(q, base, align); + DBG_RW_IVAL("num_auths ", depth, base, io, q, sid->num_auths); q += 4; DBG_RW_CVAL("sid_no ", depth, base, io, q, sid->sid_no); q++; DBG_RW_CVAL("num_auths ", depth, base, io, q, sid->num_auths); q++; -- cgit From 781be1daac75092666c1753f21871f2923a6f775 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Tue, 14 Oct 1997 19:32:30 +0000 Subject: Added a very small piece of documentation to describe the binary tree modules. --- source/ubiqx/BinaryTrees.readme | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 source/ubiqx/BinaryTrees.readme diff --git a/source/ubiqx/BinaryTrees.readme b/source/ubiqx/BinaryTrees.readme new file mode 100644 index 00000000000..ec99a43d17f --- /dev/null +++ b/source/ubiqx/BinaryTrees.readme @@ -0,0 +1,24 @@ +Short: Binary AVL & Splay trees non-recursive. +Uploader: crh@ubiqx.mn.org (Christopher R. Hertel) +Author: crh@ubiqx.mn.org (Christopher R. Hertel) +Type: dev/c +Version: 2.4. + +Written in C using OOP techniques, these modules provide three forms of +binary tree: Simple (unbalanced) AVL (height-balanced), and Splay. AVL +trees are re-balanced after every insertion or deletion. For each node in +the tree, the difference in height between the left and right subtree is +at most 1. Splay trees use a different approach. Each time a node is +accessed (inserted, deleted, or directly found via a search), the node is +bubbled to the top of the tree. This has the effect of making the tree +'bushier' and placing the most frequently accessed nodes nearer to the +top. + +The functions are non-recursive to limit stack space usage, and can also +be made into a run-time library. The type of tree used is determined by +which header file is included with your program. No other code changes +are necessary. + +Pretty darn fast, too, IMHO. + +Chris Hertel -- cgit From df3bafd0c488760b1909329c899102d92a2fe16b Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Wed, 15 Oct 1997 01:16:37 +0000 Subject: First draft of a README file to explain the origins of the "ubiqx" code. --- source/ubiqx/README | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 source/ubiqx/README diff --git a/source/ubiqx/README b/source/ubiqx/README new file mode 100644 index 00000000000..84334906518 --- /dev/null +++ b/source/ubiqx/README @@ -0,0 +1,20 @@ +This directory contains a set of utility modules that are being used with +Samba. The modules themselves do not require Samba, and may be used and +distributed independantly, under the terms of the GNU LIBRARY GENERAL +PUBLIC LICENSE (LGPL). A copy of LGPL should also be included in this +directory under the name COPYING. If this file is not present, you can +obtain a copy of the LGPL by writing to the Free Software Foundation, +Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +The modules included are: + +ubi_dLinkList - Simple doubly linked lists. +ubi_BinTree - Simple binary trees. +ubi_AVLtree - AVL height balanced binary trees (requires (ubi_BinTree). +ubi_SplayTree - Splay balanced binary trees (requires (ubi_BinTree). + +See http://www.interads.co.uk/~crh/ubiqx/ for more information. + +Chris Hertel +Samba Team +samba-bugs@samba.anu.edu.au -- cgit From 4200f5a328e1934d4d9cbc4e069e723b639a49db Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Wed, 15 Oct 1997 01:34:04 +0000 Subject: Added #ifdef'ed code with BIND_LOCAL_OUTPUT_SOCKET that causes optput sockets to be bound to the same local address as input ones are. Jeremy (jallison@whistle.com) --- source/lib/util.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source/lib/util.c b/source/lib/util.c index 459745b8b14..54b2dc08ac8 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3035,8 +3035,26 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) if (res == -1) { DEBUG(0,("socket error\n")); return -1; } - if (type != SOCK_STREAM) return(res); +#ifdef BIND_LOCAL_OUTPUT_SOCKET + { + struct sockaddr_in sock_in; + /* Bind the local part of this socket to the address + given in the socket address parameter. */ + + bzero((char *)&sock_in,sizeof(sock_in)); + putip((char *)&sock_in.sin_addr,(char *)interpret_addr2(lp_socket_address())); + sock_in.sin_port = 0; + sock_in.sin_family = PF_INET; + + if (bind(res, (struct sockaddr * ) &sock_in,sizeof(sock_in)) < 0) + DEBUG(0,("Failed to bind local socket address for output socket. Error was %s\n", + strerror(errno))); + } +#endif /* BIND_LOCAL_OUTPUT_SOCKET */ + + if (type != SOCK_STREAM) return(res); + bzero((char *)&sock_out,sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); -- cgit From 128a4422baa2f642fca0a6a19756136d57f5d37c Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Wed, 15 Oct 1997 01:34:56 +0000 Subject: Updated for 1.9.17p3 release. Jeremy (jallison@whistle,com): --- WHATSNEW.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index b3aa7d78a17..3ce008ff66c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,4 +1,4 @@ - WHATS NEW IN 1.9.17p2 - October 13th 1997 + WHATS NEW IN 1.9.17p2 - October 14th 1997 =========================================== Update release: Samba - version 1.9.17p3. @@ -11,7 +11,7 @@ for all current bug-fixes. Here are a list of the fixes in this release (the fixes introduced between 1.9.17p2 and 1.9.17p3) : -1). Truncation of long browse lists. +1). Removed truncation problem with long browse lists. 2). Crash bug when dead share mode memory entries need removing. 3). Race condition in slow share mode code. 4). Potential buffer overflow from password server. @@ -24,6 +24,8 @@ introduced between 1.9.17p2 and 1.9.17p3) : 10). Wrapping log file causes incorrect errors to be returned to the clients. 11). Crash fix for nmbd Get_Hostbyname bad return. +12). 'become_root' 'unbecome_root' added to fix changing uid problems. +13). No magic scripts or printing done on exceptional file close problems. Reporting bugs -------------- -- cgit From a173a1495c50b5ad1f6b47710cf4b4a7a2226b46 Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Wed, 15 Oct 1997 01:38:13 +0000 Subject: preparing for release of 1.9.17p3 --- source/include/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/include/version.h b/source/include/version.h index 76ccca122c6..7bea7836bc6 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.17p2" +#define VERSION "1.9.17p3" -- cgit From 2181d929d1757aa523e7afaf0e8c232a51e68d30 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Wed, 15 Oct 1997 03:11:46 +0000 Subject: These are the ubiqx modules, as included with the Samba distribution. Updated the linked list module, which has new and changed macros. --- source/ubiqx/ubi_dLinkList.c | 15 +++++++++---- source/ubiqx/ubi_dLinkList.h | 52 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/source/ubiqx/ubi_dLinkList.c b/source/ubiqx/ubi_dLinkList.c index 0bec3323edc..2eb721e1eed 100644 --- a/source/ubiqx/ubi_dLinkList.c +++ b/source/ubiqx/ubi_dLinkList.c @@ -25,10 +25,17 @@ * -------------------------------------------------------------------------- ** * * $Log: ubi_dLinkList.c,v $ - * Revision 1.1 1997/10/10 14:46:43 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) + * Revision 1.2 1997/10/15 03:11:46 crh + * These are the ubiqx modules, as included with the Samba distribution. + * Updated the linked list module, which has new and changed macros. + * + * Revision 0.3 1997/10/15 03:05:39 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:07:21 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). * * Revision 0.1 1997/10/07 04:34:07 crh * Initial Revision. diff --git a/source/ubiqx/ubi_dLinkList.h b/source/ubiqx/ubi_dLinkList.h index 5204f35eaf7..802513aaf9b 100644 --- a/source/ubiqx/ubi_dLinkList.h +++ b/source/ubiqx/ubi_dLinkList.h @@ -27,10 +27,17 @@ * -------------------------------------------------------------------------- ** * * $Log: ubi_dLinkList.h,v $ - * Revision 1.1 1997/10/10 14:46:43 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) + * Revision 1.2 1997/10/15 03:11:46 crh + * These are the ubiqx modules, as included with the Samba distribution. + * Updated the linked list module, which has new and changed macros. + * + * Revision 0.3 1997/10/15 03:04:31 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:08:16 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). * * Revision 0.1 1997/10/07 04:34:38 crh * Initial Revision. @@ -74,29 +81,50 @@ typedef ubi_dlList *ubi_dlListPtr; * * ubi_dlAddHead - Add a new node at the head of the list. * ubi_dlAddTail - Add a new node at the tail of the list. + * ubi_dlAddHere - Add a node following the given node. * ubi_dlRemHead - Remove the node at the head of the list, if any. * ubi_dlRemTail - Remove the node at the tail of the list, if any. + * ubi_dlRemThis - Remove the indicated node. * ubi_dlFirst - Return a pointer to the first node in the list, if any. * ubi_dlLast - Return a pointer to the last node in the list, if any. * ubi_dlNext - Given a node, return a pointer to the next node. * ubi_dlPrev - Given a node, return a pointer to the previous node. + * + * Note that all of these provide type casting of the parameters. The + * Add and Rem macros are nothing more than nice front-ends to the + * Insert and Remove operations. + * */ -#define ubi_dlAddHead( L, N ) ubi_dlInsert( (L), (N), NULL ) +#define ubi_dlAddHead( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL ) + +#define ubi_dlAddTail( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (((ubi_dlListPtr)(L))->Tail) ) + +#define ubi_dlAddHere( L, N, P ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (ubi_dlNodePtr)(P) ) -#define ubi_dlAddTail( L, N ) ubi_dlInsert( (L), (N), ((L)->Tail) ) +#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Head) ) -#define ubi_dlRemHead( L ) ubi_dlRemove( (L), ((L)->Head) ) +#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Tail) ) -#define ubi_dlRemTail( L ) ubi_dlRemove( (L), ((L)->Tail) ) +#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N) ) -#define ubi_dlFirst( L ) ((L)->Head) +#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head) -#define ubi_dlLast( L ) ((L)->Tail) +#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail) -#define ubi_dlNext( N ) ((N)->Next) +#define ubi_dlNext( N ) (((ubi_dlNodePtr)(N))->Next) -#define ubi_dlPrev( N ) ((N)->Prev) +#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev) /* ========================================================================== ** -- cgit From 45f4ae4327a8836cad22bbf64f1effba6a6eb7f5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 04:04:38 +0000 Subject: force the salt to be a maximum of 2 characters long in calls to crypt() This might solve some password problems, particulary on HPUX --- source/smbd/password.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/smbd/password.c b/source/smbd/password.c index af9be289c7d..1b1bd34bcca 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1047,6 +1047,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) /* extract relevant info */ strcpy(this_user,pass->pw_name); strcpy(this_salt,pass->pw_passwd); + this_salt[2] = 0; strcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { -- cgit From 708edc348f0fb81d9c918e4bf857f339a13a3781 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 04:51:23 +0000 Subject: fixed a stack overflow bug in api_lsa_req_chal() changed the order of arguments to smbhash() in credentials.c. Luke, when you changed from E1() to smbhash() you didn't notice that the arguments are in a different order. This is why your new code was failing. NT logon still fails, but now gets to SAMLOGON. It shouldn't take much to get it working now. --- source/libsmb/credentials.c | 8 ++++---- source/pipenetlog.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index 07816bc0cf2..babc8180f2c 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -44,8 +44,8 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - smbhash(pass , sum2, buf); - smbhash(pass+9, buf , netsesskey); + smbhash(buf, sum2, pass); + smbhash(netsesskey, buf, pass+9); session_key[0] = IVAL(netsesskey, 0); session_key[1] = IVAL(netsesskey, 4); @@ -86,10 +86,10 @@ void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, SIVAL(timecred, 0, IVAL(stor_cred, 0) + timestamp.time); SIVAL(timecred, 4, IVAL(stor_cred, 4)); - smbhash(netsesskey, timecred, buf); + smbhash(buf, timecred, netsesskey); memset(key2, 0, 7); key2[0] = netsesskey[7]; - smbhash(key2, buf, calc_cred); + smbhash(calc_cred, buf, key2); cred->data[0] = IVAL(calc_cred, 0); cred->data[1] = IVAL(calc_cred, 4); diff --git a/source/pipenetlog.c b/source/pipenetlog.c index acb7f806b94..6d406ee7d2a 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -292,7 +292,7 @@ static BOOL update_dcinfo(int cnum, uint16 vuid, } { - char foo[16]; + fstring foo; for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]); DEBUG(4,("pass %s %s\n", mach_acct, foo)); } -- cgit From e1e86c1a160c8302004ea58e4f0f5874dd179dae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 09:15:45 +0000 Subject: fixed the freeze on logout bug. The fix has several parts: 1) add a new parameter to queue_netbios_packet(), the "reply_id", this is the id that should be used when sending a further response to the packet (such as a response after we get back a reply to a name query after senidnga WACK). reply_id is 0 (meaning unused) in most cases. 2) fix the id used in the reply in add_name_respond() from response_name_query_register() 3) remember to remove the response record at the end of response_name_query_register() 4) get the right IP address (it was 0.0.0.0) in response_name_query_register() 5) add a new field reply_id to struct response_record --- source/include/nameserv.h | 1 + source/nameannounce.c | 2 +- source/namebrowse.c | 2 +- source/namedbresp.c | 4 +++- source/nameelect.c | 2 +- source/namepacket.c | 13 +++++++++---- source/nameresp.c | 10 ++++++---- source/nameserv.c | 9 +++++---- source/nameservreply.c | 8 +++++--- source/nameservresp.c | 10 ++++++---- source/namework.c | 3 ++- 11 files changed, 40 insertions(+), 24 deletions(-) diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 593c101d92f..81487e9ce9a 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -247,6 +247,7 @@ struct response_record BOOL recurse; struct in_addr send_ip; struct in_addr reply_to_ip; + int reply_id; int num_msgs; diff --git a/source/nameannounce.c b/source/nameannounce.c index d3344ebd478..d69ee32ddf7 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -469,7 +469,7 @@ for workgroup %s\n", name, type, inet_ntoa(nr->ip_flgs[0].ip), work->work_group NMB_QUERY,NAME_STATUS_DOM_SRV_CHK, name, type, 0,0,0, work->work_group,NULL, - False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip); + False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip, 0); } } diff --git a/source/namebrowse.c b/source/namebrowse.c index 1dd293d27be..ae5f00ce10e 100644 --- a/source/namebrowse.c +++ b/source/namebrowse.c @@ -199,7 +199,7 @@ workgroup %s\n", queue_netbios_packet(d,ClientNMB,NMB_QUERY, b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, b->name,0x20,0,0,0,NULL,b->group, - False,False,b->ip,b->ip); + False,False,b->ip,b->ip, 0); b->synced = True; } diff --git a/source/namedbresp.c b/source/namedbresp.c index 86d7eddbd41..c8a31a6c79b 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -95,7 +95,8 @@ struct response_record *make_response_queue_record(enum state_type state, int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id) { struct response_record *n; @@ -118,6 +119,7 @@ struct response_record *make_response_queue_record(enum state_type state, n->recurse = recurse; n->send_ip = send_ip; n->reply_to_ip = reply_to_ip; + n->reply_id = reply_id; if(my_name) StrnCpy(n->my_name, my_name, sizeof(n->my_name)-1); else diff --git a/source/nameelect.c b/source/nameelect.c index 5fd1a4bdf2e..215ee94febb 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -97,7 +97,7 @@ void check_master_browser(time_t t) queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, work->work_group,0x1d,0,0,0,NULL,NULL, - True,False,d->bcast_ip,d->bcast_ip); + True,False,d->bcast_ip,d->bcast_ip, 0); } } } diff --git a/source/namepacket.c b/source/namepacket.c index ba2497d7de0..4a9f586a762 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -37,6 +37,7 @@ extern int num_response_packets; BOOL CanRecurse = True; extern pstring scope; extern struct in_addr wins_ip; +extern struct in_addr loopback_ip; static uint16 name_trn_id=0; @@ -228,14 +229,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, } default: { - DEBUG(1,("replying netbios packet: %s %s\n", + DEBUG(1,("replying netbios packet: %s %s %s\n", packet_type, namestr(rr_name), inet_ntoa(p.ip))); return; } } - DEBUG(4,("replying netbios packet: %s %s\n", + DEBUG(4,("replying netbios packet: %s %s %s\n", packet_type, namestr(rr_name), inet_ntoa(p.ip))); nmb->header.name_trn_id = trn_id; @@ -534,7 +535,9 @@ void listen_for_packets(BOOL run_election) struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); if (packet) { - if (ismyip(packet->ip) && packet->port == NMB_PORT) + if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && + packet->port == NMB_PORT) { DEBUG(7,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); @@ -552,7 +555,9 @@ void listen_for_packets(BOOL run_election) struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); if (packet) { - if (ismyip(packet->ip) && packet->port == DGRAM_PORT) + if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && + packet->port == DGRAM_PORT) { DEBUG(7,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); diff --git a/source/nameresp.c b/source/nameresp.c index f44171f4b67..c40dd16a888 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -115,7 +115,7 @@ static void dead_netbios_entry(struct subnet_record *d, wanted the unique name and tell them that they can have it */ - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, + add_name_respond(d,n->fd,d->myip, n->reply_id ,&n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip, True, n->reply_to_ip); @@ -281,7 +281,7 @@ struct response_record *queue_netbios_pkt_wins( return queue_netbios_packet(wins_subnet,fd, quest_type, state, name, name_type, nb_flags, ttl, server_type,my_name,my_comment, - False, True, send_ip, reply_to_ip); + False, True, send_ip, reply_to_ip, 0); } @@ -296,7 +296,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id) { struct response_record *n; uint16 id = 0xffff; @@ -315,7 +316,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, if ((n = make_response_queue_record(state,id,fd, quest_type,name,name_type,nb_flags,ttl, server_type,my_name, my_comment, - bcast,recurse,send_ip,reply_to_ip))) + bcast,recurse,send_ip,reply_to_ip, + reply_id))) { add_response_record(d,n); return n; diff --git a/source/nameserv.c b/source/nameserv.c index ccd0ef379cb..bc37d1c424e 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -111,7 +111,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type) /* local interface: release them on the network */ queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE, name, type, 0, 0,0,NULL,NULL, - True, False, d->bcast_ip, d->bcast_ip); + True, False, d->bcast_ip, d->bcast_ip, 0); } } @@ -172,7 +172,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) queue_netbios_packet(d,ClientNMB, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, name, type, nb_flags, GET_TTL(0),0,NULL,NULL, - True, False, d->bcast_ip, ipzero); + True, False, d->bcast_ip, ipzero, 0); } } @@ -249,7 +249,7 @@ for domain master on workgroup %s\n", myworkgroup, 0x1b, 0, 0,0,NULL,NULL, True, False, - d->bcast_ip, d->bcast_ip); + d->bcast_ip, d->bcast_ip, 0); } } } @@ -488,7 +488,8 @@ void query_refresh_names(time_t t) queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, n->name.name, n->name.name_type, 0,0,0,NULL,NULL, - False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); + False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip, + 0); count++; } diff --git a/source/nameservreply.c b/source/nameservreply.c index 5b9c476549d..98247c76366 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -45,7 +45,7 @@ static void send_name_response(int fd, struct in_addr from_ip, int name_trn_id, int opcode, BOOL success, BOOL recursion_available, BOOL recursion_desired, struct nmb_name *reply_name, int nb_flags, int ttl, - struct in_addr ip) + struct in_addr ip) { char rdata[6]; struct packet_struct p; @@ -96,7 +96,8 @@ void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, /* reply yes or no to the host that requested the name */ /* see rfc1002.txt - 4.2.10 and 4.2.11 */ - send_name_response(fd,from_ip, response_id, NMB_REG, + + send_name_response(fd, reply_to_ip, response_id, NMB_REG, new_owner, True, True, name, nb_flags, ttl, reply_to_ip); @@ -317,7 +318,8 @@ void reply_name_reg(struct packet_struct *p) reply_name->name,reply_name->name_type, nb_flags,0,0,NULL,NULL, False, False, - n->ip_flgs[0].ip, p->ip); + n->ip_flgs[0].ip, p->ip, + nmb->header.name_trn_id); } else { diff --git a/source/nameservresp.c b/source/nameservresp.c index a88481d06b0..8de90113fb6 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -176,7 +176,7 @@ static void response_server_check(struct nmb_name *ans_name, queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, ans_name->name, ans_name->name_type, 0,0,0,n->my_name,NULL, - False,False,send_ip,n->reply_to_ip); + False,False,send_ip,n->reply_to_ip, 0); } @@ -362,9 +362,11 @@ static void response_name_query_register(struct nmb_packet *nmb, } /* register the old or the new owners' ip */ - add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags, + add_name_respond(d, n->fd, d->myip, n->reply_id,&n->name,n->nb_flags, GET_TTL(0), register_ip, new_owner, n->reply_to_ip); + + remove_response_record(d,n); /* remove the response record */ } @@ -829,8 +831,8 @@ void response_netbios_packet(struct packet_struct *p) } ans_name = &nmb->answers->rr_name; - DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); + DEBUG(3,("response for %s from %s(%d) (bcast=%s)\n", + namestr(ans_name), inet_ntoa(p->ip), p->port, BOOLSTR(bcast))); debug_rr_type(nmb->answers->rr_type); diff --git a/source/namework.c b/source/namework.c index 3e1ac220058..2de4a3016f7 100644 --- a/source/namework.c +++ b/source/namework.c @@ -372,7 +372,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, work->work_group,0x1d, 0,0,0,NULL,NULL, - False,False,back_ip,back_ip); + False,False,back_ip,back_ip, + 0); return; } } -- cgit From eb76fea411c5c3aa96b7158d02b49ed42ec7ba70 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 09:16:30 +0000 Subject: added loopback_ip. This is used to detect packets from ourselves --- source/lib/interface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/lib/interface.c b/source/lib/interface.c index 147425d0fc1..1dc605ff2fd 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -25,6 +25,7 @@ extern int DEBUGLEVEL; struct in_addr ipzero; struct in_addr wins_ip; +struct in_addr loopback_ip; static struct in_addr default_ip; static struct in_addr default_bcast; static struct in_addr default_nmask; @@ -262,6 +263,7 @@ static void interpret_interfaces(char *s, struct interface **interfaces, ipzero = *interpret_addr2("0.0.0.0"); wins_ip = *interpret_addr2("255.255.255.255"); + loopback_ip = *interpret_addr2("127.0.0.1"); while (next_token(&ptr,token,NULL)) { /* parse it into an IP address/netmasklength pair */ -- cgit From 97d06dd05e952a134be26ec5998ec4b8d38991dd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 09:17:21 +0000 Subject: add the port number to a debug statement --- source/libsmb/nmblib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 48f988de2a2..e8f281bc257 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -107,8 +107,8 @@ void debug_nmb_packet(struct packet_struct *p) { struct nmb_packet *nmb = &p->packet.nmb; - DEBUG(4,("nmb packet from %s header: id=%d opcode=%s(%d) response=%s\n", - inet_ntoa(p->ip), + DEBUG(4,("nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n", + inet_ntoa(p->ip), p->port, nmb->header.name_trn_id, lookup_opcode_name(nmb->header.opcode), nmb->header.opcode,BOOLSTR(nmb->header.response))); -- cgit From bdf3155418be02e2fe4daa1d2538f236be414e98 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 09:18:39 +0000 Subject: the usual proto.h update --- source/include/proto.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index ca60239412f..1ed8539ab59 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -427,7 +427,8 @@ struct response_record *make_response_queue_record(enum state_type state, int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id); struct response_record *find_response_record(struct subnet_record **d, uint16 id); @@ -529,7 +530,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id); /*The following definitions come from nameserv.c */ -- cgit From 44d60de3f7a8ace19c1a1164d300b6533e6c2c99 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Wed, 15 Oct 1997 09:39:54 +0000 Subject: added the "freeze on logout" fixes to the 1.9.17 tree --- source/include/nameserv.h | 1 + source/include/proto.h | 6 ++++-- source/lib/interface.c | 2 ++ source/libsmb/nmblib.c | 4 ++-- source/nameannounce.c | 2 +- source/namebrowse.c | 2 +- source/namedbresp.c | 4 +++- source/nameelect.c | 2 +- source/namepacket.c | 13 +++++++++---- source/nameresp.c | 10 ++++++---- source/nameserv.c | 9 +++++---- source/nameservreply.c | 8 +++++--- source/nameservresp.c | 10 ++++++---- source/namework.c | 3 ++- 14 files changed, 48 insertions(+), 28 deletions(-) diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 83f3a3c5246..b0409572ec8 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -246,6 +246,7 @@ struct response_record BOOL recurse; struct in_addr send_ip; struct in_addr reply_to_ip; + int reply_id; int num_msgs; diff --git a/source/include/proto.h b/source/include/proto.h index d7cbc4cc4c4..718d92495fc 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -394,7 +394,8 @@ struct response_record *make_response_queue_record(enum state_type state, int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id); struct response_record *find_response_record(struct subnet_record **d, uint16 id); @@ -496,7 +497,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip); + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id); /*The following definitions come from nameserv.c */ diff --git a/source/lib/interface.c b/source/lib/interface.c index 147425d0fc1..1dc605ff2fd 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -25,6 +25,7 @@ extern int DEBUGLEVEL; struct in_addr ipzero; struct in_addr wins_ip; +struct in_addr loopback_ip; static struct in_addr default_ip; static struct in_addr default_bcast; static struct in_addr default_nmask; @@ -262,6 +263,7 @@ static void interpret_interfaces(char *s, struct interface **interfaces, ipzero = *interpret_addr2("0.0.0.0"); wins_ip = *interpret_addr2("255.255.255.255"); + loopback_ip = *interpret_addr2("127.0.0.1"); while (next_token(&ptr,token,NULL)) { /* parse it into an IP address/netmasklength pair */ diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 29b54a708bc..95217b7eded 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -107,8 +107,8 @@ void debug_nmb_packet(struct packet_struct *p) { struct nmb_packet *nmb = &p->packet.nmb; - DEBUG(4,("nmb packet from %s header: id=%d opcode=%s(%d) response=%s\n", - inet_ntoa(p->ip), + DEBUG(4,("nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n", + inet_ntoa(p->ip), p->port, nmb->header.name_trn_id, lookup_opcode_name(nmb->header.opcode), nmb->header.opcode,BOOLSTR(nmb->header.response))); diff --git a/source/nameannounce.c b/source/nameannounce.c index 84e3ad3fa77..c85561b763a 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -469,7 +469,7 @@ for workgroup %s\n", name, type, inet_ntoa(nr->ip_flgs[0].ip), work->work_group NMB_QUERY,NAME_STATUS_DOM_SRV_CHK, name, type, 0,0,0, work->work_group,NULL, - False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip); + False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip, 0); } } diff --git a/source/namebrowse.c b/source/namebrowse.c index 1dd293d27be..ae5f00ce10e 100644 --- a/source/namebrowse.c +++ b/source/namebrowse.c @@ -199,7 +199,7 @@ workgroup %s\n", queue_netbios_packet(d,ClientNMB,NMB_QUERY, b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, b->name,0x20,0,0,0,NULL,b->group, - False,False,b->ip,b->ip); + False,False,b->ip,b->ip, 0); b->synced = True; } diff --git a/source/namedbresp.c b/source/namedbresp.c index 86d7eddbd41..c8a31a6c79b 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -95,7 +95,8 @@ struct response_record *make_response_queue_record(enum state_type state, int quest_type, char *name,int type, int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id) { struct response_record *n; @@ -118,6 +119,7 @@ struct response_record *make_response_queue_record(enum state_type state, n->recurse = recurse; n->send_ip = send_ip; n->reply_to_ip = reply_to_ip; + n->reply_id = reply_id; if(my_name) StrnCpy(n->my_name, my_name, sizeof(n->my_name)-1); else diff --git a/source/nameelect.c b/source/nameelect.c index 5c156a312ed..b2e4ab62492 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -97,7 +97,7 @@ void check_master_browser(time_t t) queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, work->work_group,0x1d,0,0,0,NULL,NULL, - True,False,d->bcast_ip,d->bcast_ip); + True,False,d->bcast_ip,d->bcast_ip, 0); } } } diff --git a/source/namepacket.c b/source/namepacket.c index 44e449b8c2a..fb8e4d2bf5b 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -37,6 +37,7 @@ extern int num_response_packets; BOOL CanRecurse = True; extern pstring scope; extern struct in_addr wins_ip; +extern struct in_addr loopback_ip; static uint16 name_trn_id=0; @@ -228,14 +229,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, } default: { - DEBUG(1,("replying netbios packet: %s %s\n", + DEBUG(1,("replying netbios packet: %s %s %s\n", packet_type, namestr(rr_name), inet_ntoa(p.ip))); return; } } - DEBUG(4,("replying netbios packet: %s %s\n", + DEBUG(4,("replying netbios packet: %s %s %s\n", packet_type, namestr(rr_name), inet_ntoa(p.ip))); nmb->header.name_trn_id = trn_id; @@ -528,7 +529,9 @@ void listen_for_packets(BOOL run_election) struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); if (packet) { - if (ismyip(packet->ip) && packet->port == NMB_PORT) + if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && + packet->port == NMB_PORT) { DEBUG(7,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); @@ -546,7 +549,9 @@ void listen_for_packets(BOOL run_election) struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); if (packet) { - if (ismyip(packet->ip) && packet->port == DGRAM_PORT) + if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && + packet->port == DGRAM_PORT) { DEBUG(7,("discarding own packet from %s:%d\n", inet_ntoa(packet->ip),packet->port)); diff --git a/source/nameresp.c b/source/nameresp.c index f44171f4b67..c40dd16a888 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -115,7 +115,7 @@ static void dead_netbios_entry(struct subnet_record *d, wanted the unique name and tell them that they can have it */ - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, + add_name_respond(d,n->fd,d->myip, n->reply_id ,&n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip, True, n->reply_to_ip); @@ -281,7 +281,7 @@ struct response_record *queue_netbios_pkt_wins( return queue_netbios_packet(wins_subnet,fd, quest_type, state, name, name_type, nb_flags, ttl, server_type,my_name,my_comment, - False, True, send_ip, reply_to_ip); + False, True, send_ip, reply_to_ip, 0); } @@ -296,7 +296,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) + struct in_addr send_ip, struct in_addr reply_to_ip, + int reply_id) { struct response_record *n; uint16 id = 0xffff; @@ -315,7 +316,8 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, if ((n = make_response_queue_record(state,id,fd, quest_type,name,name_type,nb_flags,ttl, server_type,my_name, my_comment, - bcast,recurse,send_ip,reply_to_ip))) + bcast,recurse,send_ip,reply_to_ip, + reply_id))) { add_response_record(d,n); return n; diff --git a/source/nameserv.c b/source/nameserv.c index ccd0ef379cb..bc37d1c424e 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -111,7 +111,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type) /* local interface: release them on the network */ queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE, name, type, 0, 0,0,NULL,NULL, - True, False, d->bcast_ip, d->bcast_ip); + True, False, d->bcast_ip, d->bcast_ip, 0); } } @@ -172,7 +172,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) queue_netbios_packet(d,ClientNMB, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, name, type, nb_flags, GET_TTL(0),0,NULL,NULL, - True, False, d->bcast_ip, ipzero); + True, False, d->bcast_ip, ipzero, 0); } } @@ -249,7 +249,7 @@ for domain master on workgroup %s\n", myworkgroup, 0x1b, 0, 0,0,NULL,NULL, True, False, - d->bcast_ip, d->bcast_ip); + d->bcast_ip, d->bcast_ip, 0); } } } @@ -488,7 +488,8 @@ void query_refresh_names(time_t t) queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, n->name.name, n->name.name_type, 0,0,0,NULL,NULL, - False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); + False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip, + 0); count++; } diff --git a/source/nameservreply.c b/source/nameservreply.c index 5b9c476549d..98247c76366 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -45,7 +45,7 @@ static void send_name_response(int fd, struct in_addr from_ip, int name_trn_id, int opcode, BOOL success, BOOL recursion_available, BOOL recursion_desired, struct nmb_name *reply_name, int nb_flags, int ttl, - struct in_addr ip) + struct in_addr ip) { char rdata[6]; struct packet_struct p; @@ -96,7 +96,8 @@ void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, /* reply yes or no to the host that requested the name */ /* see rfc1002.txt - 4.2.10 and 4.2.11 */ - send_name_response(fd,from_ip, response_id, NMB_REG, + + send_name_response(fd, reply_to_ip, response_id, NMB_REG, new_owner, True, True, name, nb_flags, ttl, reply_to_ip); @@ -317,7 +318,8 @@ void reply_name_reg(struct packet_struct *p) reply_name->name,reply_name->name_type, nb_flags,0,0,NULL,NULL, False, False, - n->ip_flgs[0].ip, p->ip); + n->ip_flgs[0].ip, p->ip, + nmb->header.name_trn_id); } else { diff --git a/source/nameservresp.c b/source/nameservresp.c index a88481d06b0..8de90113fb6 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -176,7 +176,7 @@ static void response_server_check(struct nmb_name *ans_name, queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, ans_name->name, ans_name->name_type, 0,0,0,n->my_name,NULL, - False,False,send_ip,n->reply_to_ip); + False,False,send_ip,n->reply_to_ip, 0); } @@ -362,9 +362,11 @@ static void response_name_query_register(struct nmb_packet *nmb, } /* register the old or the new owners' ip */ - add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags, + add_name_respond(d, n->fd, d->myip, n->reply_id,&n->name,n->nb_flags, GET_TTL(0), register_ip, new_owner, n->reply_to_ip); + + remove_response_record(d,n); /* remove the response record */ } @@ -829,8 +831,8 @@ void response_netbios_packet(struct packet_struct *p) } ans_name = &nmb->answers->rr_name; - DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); + DEBUG(3,("response for %s from %s(%d) (bcast=%s)\n", + namestr(ans_name), inet_ntoa(p->ip), p->port, BOOLSTR(bcast))); debug_rr_type(nmb->answers->rr_type); diff --git a/source/namework.c b/source/namework.c index 3e1ac220058..2de4a3016f7 100644 --- a/source/namework.c +++ b/source/namework.c @@ -372,7 +372,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, work->work_group,0x1d, 0,0,0,NULL,NULL, - False,False,back_ip,back_ip); + False,False,back_ip,back_ip, + 0); return; } } -- cgit From 96b17b829fc787c15cd366eca604c09d68b5b900 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 15 Oct 1997 16:51:03 +0000 Subject: added srvsvc basic pipe, straight from paul's code. does NETSHAREENUM and NETSERVERGETINFO. --- source/include/proto.h | 4 +++ source/include/smb.h | 3 ++ source/smbd/ipc.c | 2 ++ source/smbd/pipes.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/source/include/proto.h b/source/include/proto.h index 1ed8539ab59..6baa945e8b9 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -654,6 +654,10 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); +BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); /*The following definitions come from pipeutil.c */ diff --git a/source/include/smb.h b/source/include/smb.h index 8e34b063596..c733f295210 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -293,6 +293,9 @@ typedef fstring string; #define LSA_LOOKUPNAMES 0xFD #define LSA_SAMLOGOFF 0xFC +/* srvsvc pipe */ +#define NETSERVERGETINFO 0x15 +#define NETSHAREENUM 0x0f /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ typedef struct time_info diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 468d34e157f..c29e8656b17 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2764,8 +2764,10 @@ struct { #ifdef NTDOMAIN { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "SetNmdPpHndState", "srvsvc", 1, api_LsarpcSNPHS }, { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS }, { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, + { "TransactNmPipe", "srvsvc", 0x26, api_srvsvcTNP }, { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP }, #else { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 91ca69c0226..bf53fa84bc2 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -55,6 +55,7 @@ char * known_pipes [] = "lsarpc", #if NTDOMAIN "NETLOGON", + "srvsvc", #endif NULL }; @@ -362,3 +363,84 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, } return(True); } + +BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + int pkttype; + extern pstring myname; + char *servername; + uint32 level; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("srvsvc rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("srvsvc TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("srvsvc LINE %d\n",__LINE__)); + get_myname(myname,NULL); + switch (opnum) + { + case NETSHAREENUM: + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, level); q += 4; + SIVAL(q, 0, 1); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; + SIVAL(q, 0, 2); q += 4; /* number of entries */ + SIVAL(q, 0, 2); q += 4; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + case NETSERVERGETINFO: + { + UNISTR2 uni_str; + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, 101); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; /* bufptr */ + SIVAL(q, 0, 0x1f4); q += 4; /* platform id */ + SIVAL(q, 0, 2); q += 4; /* bufptr for name */ + SIVAL(q, 0, 5); q += 4; /* major version */ + SIVAL(q, 0, 4); q += 4; /* minor version == 5.4 */ + SIVAL(q, 0, 0x4100B); q += 4; /* type */ + SIVAL(q, 0, 2); q += 4; /* comment */ + make_unistr2(&uni_str, myname, strlen(myname)); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + make_unistr2(&uni_str, lp_serverstring(), strlen(lp_serverstring())); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + q = align_offset(q, *rdata, 4); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + } + default: + DEBUG(4, ("srvsvc, unknown code: %lx\n", opnum)); + } + return(True); +} + -- cgit From e55a3dc94a824b61a7123b080705be2271268ee4 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Wed, 15 Oct 1997 17:59:58 +0000 Subject: Added ubi_sLinkList module which manages simple singly-linked lists. --- source/ubiqx/Makefile | 7 ++- source/ubiqx/ubi_sLinkList.c | 102 +++++++++++++++++++++++++++++++++ source/ubiqx/ubi_sLinkList.h | 133 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 source/ubiqx/ubi_sLinkList.c create mode 100644 source/ubiqx/ubi_sLinkList.h diff --git a/source/ubiqx/Makefile b/source/ubiqx/Makefile index 16fb454e77d..369f7762bfe 100644 --- a/source/ubiqx/Makefile +++ b/source/ubiqx/Makefile @@ -6,7 +6,8 @@ .SUFFIXES: .SUFFIXES: .c .o .h -all: ubi_AVLtree.o ubi_BinTree.o ubi_SplayTree.o ubi_dLinkList.o +all: ubi_AVLtree.o ubi_BinTree.o ubi_SplayTree.o \ + ubi_dLinkList.o ubi_sLinkList.o ubi_BinTree.o: ubi_BinTree.h @echo Compiling $*.c @@ -24,6 +25,10 @@ ubi_dLinkList.o: ubi_dLinkList.h @echo Compiling $*.c @$(CC) $(CFLAGS) -c $*.c +ubi_sLinkList.o: ubi_sLinkList.h + @echo Compiling $*.c + @$(CC) $(CFLAGS) -c $*.c + .c.o: @echo Compiling $*.c @$(CC) $(CFLAGS) -c $*.c diff --git a/source/ubiqx/ubi_sLinkList.c b/source/ubiqx/ubi_sLinkList.c new file mode 100644 index 00000000000..03694f4f9c7 --- /dev/null +++ b/source/ubiqx/ubi_sLinkList.c @@ -0,0 +1,102 @@ +/* ========================================================================== ** + * ubi_sLinkList.c + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements a really simple singly-linked list. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_sLinkList.c,v $ + * Revision 1.1 1997/10/15 17:59:58 crh + * Added ubi_sLinkList module which manages simple singly-linked lists. + * + * ========================================================================== ** + */ + +#include "ubi_sLinkList.h" + +/* ========================================================================== ** + * Functions... + */ + +ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a singly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_slInitList */ + +ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, + ubi_slNodePtr New ) + /* ------------------------------------------------------------------------ ** + * Insert a new node at the head of the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the node that is to be added to the list. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + New->Next = ListPtr->Head; + ListPtr->Head = New; + ++(ListPtr->count); + return( New ); + } /* ubi_slInsert */ + +ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Remove a node from the head of the list. + * + * Input: ListPtr - A pointer to the list from which the node is to be + * removed. + * + * Output: A pointer to the node that was removed. + * + * ------------------------------------------------------------------------ ** + */ + { + ubi_slNodePtr Old = ListPtr->Head; + + if( NULL != Old ) + { + ListPtr->Head = Old->Next; + --(ListPtr->count); + } + return( Old ); + } /* ubi_slRemove */ + + +/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_sLinkList.h b/source/ubiqx/ubi_sLinkList.h new file mode 100644 index 00000000000..80050e41271 --- /dev/null +++ b/source/ubiqx/ubi_sLinkList.h @@ -0,0 +1,133 @@ +#ifndef ubi_sLinkList_H +#define ubi_sLinkList_H +/* ========================================================================== ** + * ubi_sLinkList.h + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements a really simple singly-linked list. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * $Log: ubi_sLinkList.h,v $ + * Revision 1.1 1997/10/15 17:59:58 crh + * Added ubi_sLinkList module which manages simple singly-linked lists. + * + * ========================================================================== ** + */ + +#include <stdlib.h> + + +/* ========================================================================== ** + * Typedefs... + * + * ubi_slNode - This is the basic node structure. + * ubi_slNodePtr - Pointer to a node. + * ubi_slList - This is the list header structure. + * ubi_slListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_slListNode + { + struct ubi_slListNode *Next; + } ubi_slNode; + +typedef ubi_slNode *ubi_slNodePtr; + +typedef struct + { + ubi_slNodePtr Head; + unsigned long count; + } ubi_slList; + +typedef ubi_slList *ubi_slListPtr; + +/* ========================================================================== ** + * Macros... + * + * ubi_slAddHead - Add a new node at the head of the list. + * ubi_slRemHead - Remove the node at the head of the list, if any. + * ubi_slFirst - Return a pointer to the first node in the list, if any. + * ubi_slNext - Given a node, return a pointer to the next node. + * + * Note that all of these provide type casting of the parameters. The + * Add and Rem macros are nothing more than nice front-ends to the + * Insert and Remove operations. + * + */ + +#define ubi_slAddHead( L, N ) \ + ubi_slInsert( (ubi_slListPtr)(L), (ubi_slNodePtr)(N) ) + +#define ubi_slRemHead( L ) ubi_slRemove( (ubi_slListPtr)(L) ) + +#define ubi_slFirst( L ) (((ubi_slListPtr)(L))->Head) + +#define ubi_slNext( N ) (((ubi_slNodePtr)(N))->Next) + + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a singly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, + ubi_slNodePtr New ); + /* ------------------------------------------------------------------------ ** + * Insert a new node at the head of the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the node that is to be added to the list. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Remove a node from the head of the list. + * + * Input: ListPtr - A pointer to the list from which the node is to be + * removed. + * + * Output: A pointer to the node that was removed. + * + * ------------------------------------------------------------------------ ** + */ + +/* ================================ The End ================================= */ +#endif /* ubi_sLinkList_H */ -- cgit From ed606bc7d4e6fb1091e527ea70a3e950d50a1db4 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Wed, 15 Oct 1997 19:16:38 +0000 Subject: smb.h smbparse.c pipenetlog.c : whoops, the SAM Logon structure was wrong. updated this, and cifsntdomain.txt. more debug info in pipenetlog.c. the crash is somewhere around deal_with_credentials(). byteorder.h : put in uint8, uint16 and uint32 typecasts around debug info, because sign extending was resulting in ffffffe8 being displayed instead of e8. credentials.c : some debugging info, because i'm tracking a coredump. without gdb. nothing like making things difficult. reply.c : whoops, missed this (important) bit from paul's code, which tells the NT workstation that the MACHINE$ entry doesn't already exist, and we're going to create a default entry with a password "machine" right now. proto.h: the usual. --- source/include/byteorder.h | 8 ++++---- source/include/proto.h | 2 ++ source/include/smb.h | 26 ++++++++++++++++++++++---- source/libsmb/credentials.c | 3 +-- source/pipenetlog.c | 36 ++++++++++++++++++++++++++++-------- source/smbd/reply.c | 25 ++++++++++++++++++++++++- source/smbparse.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 122 insertions(+), 21 deletions(-) diff --git a/source/include/byteorder.h b/source/include/byteorder.h index e11771c3abe..f43159ecf4e 100644 --- a/source/include/byteorder.h +++ b/source/include/byteorder.h @@ -206,27 +206,27 @@ it also defines lots of intermediate macros, just ignore those :-) RW_PCVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (uint8)((outbuf)[idx]))); } } \ DEBUG(5,("\n")); #define DBG_RW_PSVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PSVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (uint16)((outbuf)[idx]))); } } \ DEBUG(5,("\n")); #define DBG_RW_PIVAL(string,depth,base,read,inbuf,outbuf,len) \ RW_PIVAL(read,inbuf,outbuf,len) \ DEBUG(5,("%s%04x %s: ", \ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \ - { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (uint32)((outbuf)[idx]))); } } \ DEBUG(5,("\n")); #define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ RW_CVAL(read,inbuf,outbuf,0) \ DEBUG(5,("%s%04x %s: %02x\n", \ - tab_depth(depth), PTR_DIFF(inbuf,base),string, *(inbuf))); + tab_depth(depth), PTR_DIFF(inbuf,base),string, *((uint8*)(inbuf)))); #define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \ RW_SVAL(read,inbuf,outbuf,0) \ diff --git a/source/include/proto.h b/source/include/proto.h index 6baa945e8b9..70a9873d340 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -855,9 +855,11 @@ char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align, int de char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int depth); char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, int depth); char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, int depth); +char* smb_io_clnt_srv(BOOL io, DOM_CLNT_SRV *log, char *q, char *base, int align, int depth); char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align, int depth); char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int depth); char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int depth); +char* smb_io_clnt_info2(BOOL io, DOM_CLNT_INFO2 *clnt, char *q, char *base, int align, int depth); char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align, int depth); char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align, int depth); char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align, int depth); diff --git a/source/include/smb.h b/source/include/smb.h index c733f295210..03cdc78e039 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -383,6 +383,16 @@ typedef struct domrid2_info } DOM_RID2; +/* DOM_CLNT_SRV - client / server names */ +typedef struct clnt_srv_info +{ + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_comp_name; /* client machine name */ + +} DOM_CLNT_SRV; + /* DOM_LOG_INFO - login info */ typedef struct log_info { @@ -417,6 +427,14 @@ typedef struct clnt_info } DOM_CLNT_INFO; +/* DOM_CLNT_INFO2 - client info */ +typedef struct clnt_info2 +{ + DOM_CLNT_SRV login; + DOM_CRED cred; + +} DOM_CLNT_INFO2; + /* DOM_LOGON_ID - logon id */ typedef struct logon_info { @@ -452,10 +470,10 @@ typedef struct id_info_1 /* SAM_INFO - sam logon/off id structure */ typedef struct sam_info { - DOM_CLNT_INFO client; - DOM_CRED rtn_cred; /* return credentials */ - uint16 logon_level; - uint32 auth_level; /* undocumented */ + DOM_CLNT_INFO2 client; + DOM_CRED rtn_cred; /* return credentials */ + uint16 logon_level; + uint32 auth_level; /* undocumented */ union { diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index babc8180f2c..d56598e98a3 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -99,7 +99,7 @@ void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, DEBUG(5,(" sess_key : %lx %lx\n", session_key [0], session_key [1])); DEBUG(5,(" stor_cred: %lx %lx\n", stor_cred->data[0], stor_cred->data[1])); - DEBUG(5,(" timecred : %lx %lx\n", IVAL(timecred, 0), IVAL(timecred, 4))); + DEBUG(5,(" timecred : %lx %lx\n", IVAL(timecred, 0) , IVAL(timecred, 4) )); DEBUG(5,(" calc_cred: %lx %lx\n", cred ->data[0], cred ->data[1])); } @@ -129,7 +129,6 @@ int cred_assert(DOM_CHAL *cred, uint32 session_key[2], DOM_CHAL *stored_cred, DEBUG(5,(" challenge : %lx %lx\n", cred->data[0], cred->data[1])); DEBUG(5,(" calculated: %lx %lx\n", cred2.data[0], cred2.data[1])); - DEBUG(5,(" challenge: ")); return memcmp(cred->data, cred2.data, 8) == 0; } diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 6d406ee7d2a..d221b8e644e 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -86,11 +86,15 @@ static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, return PTR_DIFF(q, base); } -static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, +static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_s, DOM_CRED *srv_cred, int status) { - memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred)); - r_a->status = status; + DEBUG(5,("make_lsa_r_srv_pwset: %d\n", __LINE__)); + + memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred)); + r_s->status = status; + + DEBUG(5,("make_lsa_r_srv_pwset: %d\n", __LINE__)); } static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, @@ -98,12 +102,16 @@ static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, { LSA_R_SRV_PWSET r_s; + DEBUG(5,("lsa_srv_pwset: %d\n", __LINE__)); + /* set up the LSA Server Password Set response */ make_lsa_r_srv_pwset(&r_s, srv_cred, status); /* store the response in the SMB stream */ q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0); + DEBUG(5,("lsa_srv_pwset: %d\n", __LINE__)); + /* return length of SMB data stored */ return PTR_DIFF(q, base); } @@ -395,14 +403,24 @@ static BOOL deal_with_credentials(user_struct *vuser, /* increment client time by one second */ new_clnt_time.time = clnt_cred->timestamp.time + 1; + DEBUG(5,("deal_with_credentials: new_clnt_time=%lx\n", new_clnt_time.time)); + /* create server credentials for inclusion in the reply */ cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &(srv_cred->challenge)); + + DEBUG(5,("deal_with_credentials: %d\n", __LINE__)); + + DEBUG(5,("deal_with_credentials: clnt_cred[0]=%lx\n", + vuser->dc.clnt_cred.data[0])); + + new_cred = IVAL(vuser->dc.clnt_cred.data, 0); + new_cred += new_clnt_time.time; - /* update the client and server credentials, for use next time... */ - new_cred = IVAL(vuser->dc.clnt_cred.data, 0) + new_clnt_time.time; - SIVAL(vuser->dc.clnt_cred.data, new_cred, 0); - SIVAL(vuser->dc.srv_cred.data , new_cred, 0); + DEBUG(5,("deal_with_credentials: new_cred[0]=%lx\n", new_cred)); + + SIVAL(vuser->dc.clnt_cred.data, 0, new_cred); + SIVAL(vuser->dc.srv_cred .data, 0, new_cred); return True; } @@ -421,6 +439,8 @@ static void api_lsa_srv_pwset( user_struct *vuser, /* checks and updates credentials. creates reply credentials */ deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred); + DEBUG(5,("api_lsa_srv_pwset: %d\n", __LINE__)); + /* construct reply. always indicate failure. nt keeps going... */ *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, &srv_cred, @@ -487,7 +507,7 @@ static void api_lsa_sam_logon( user_struct *vuser, pstrcpy(dom_sid , lp_domainsid ()); pstrcpy(my_workgroup, lp_workgroup ()); - pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer)); + pstrcpy(username, unistr2(q_l.sam_id.auth.id1.uni_user_name.buffer)); pstrcpy(my_name , myname ); strupper(my_name); diff --git a/source/smbd/reply.c b/source/smbd/reply.c index baccb762911..dffb6f05bd4 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -479,8 +479,31 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ if (user[strlen(user) - 1] == '$') { - computer_id = True; + struct smb_passwd *smb_pass; /* To check if machine account exists */ +#ifdef NTDOMAIN +/* + PAXX: Ack. We don't want to do this. The workstation trust account + with a $ on the end should exist in the local password database + or be mapped to something generic, but not modified. For NT + domain support we must reject this used in certain circumstances + with a code to indicate to the client that it is an invalid use + of a workstation trust account. NTWKS needs this error to join + a domain. This may be the source of future bugs if we cannot + be sure whether to reject this or not. +*/ + smb_pass = get_smbpwnam(user); + if(smb_pass) + { + /* PAXX: This is the NO LOGON workstation trust account stuff */ + DEBUG(4,("Rejecting workstation trust account %s",user)); + SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ + CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ + return(ERROR(0x99,0xc000)); /* 0x99 NT error, 0xc00 */ + } + computer_id = True; +#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ user[strlen(user) - 1] = '\0'; +#endif } diff --git a/source/smbparse.c b/source/smbparse.c index 64a0e640cb2..03ef5afe8e1 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -244,6 +244,27 @@ char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, i return q; } +/******************************************************************* +reads or writes a DOM_CLNT_SRV structure. +********************************************************************/ +char* smb_io_clnt_srv(BOOL io, DOM_CLNT_SRV *log, char *q, char *base, int align, int depth) +{ + if (log == NULL) return NULL; + + DEBUG(5,("%s%04x smb_io_clnt_srv\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("undoc_buffer ", depth, base, io, q, log->undoc_buffer); q += 4; + q = smb_io_unistr2(io, &(log->uni_logon_srv), q, base, align, depth); + + DBG_RW_IVAL("undoc_buffer2", depth, base, io, q, log->undoc_buffer); q += 4; + q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, align, depth); + + return q; +} + /******************************************************************* reads or writes a DOM_LOG_INFO structure. ********************************************************************/ @@ -306,6 +327,24 @@ char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int d return q; } +/******************************************************************* +reads or writes a DOM_CLNT_INFO2 structure. +********************************************************************/ +char* smb_io_clnt_info2(BOOL io, DOM_CLNT_INFO2 *clnt, char *q, char *base, int align, int depth) +{ + if (clnt == NULL) return NULL; + + DEBUG(5,("%s%04x smb_io_clnt_info2\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + q = smb_io_clnt_srv(io, &(clnt->login), q, base, align, depth); + q = smb_io_cred (io, &(clnt->cred ), q, base, align, depth); + + return q; +} + /******************************************************************* reads or writes a DOM_CLNT_INFO structure. ********************************************************************/ @@ -401,8 +440,8 @@ char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align q = align_offset(q, base, align); - q = smb_io_clnt_info(io, &(sam->client ), q, base, align, depth); - q = smb_io_cred (io, &(sam->rtn_cred), q, base, align, depth); + q = smb_io_clnt_info2(io, &(sam->client ), q, base, align, depth); + q = smb_io_cred (io, &(sam->rtn_cred), q, base, align, depth); DBG_RW_IVAL("logon_level", depth, base, io, q, sam->logon_level); q += 4; DBG_RW_SVAL("auth_level ", depth, base, io, q, sam->auth_level ); q += 4; -- cgit From 16fd4337f79ce33f91050c96c4a566221c5d9126 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Wed, 15 Oct 1997 21:53:59 +0000 Subject: ipc.c: Adding Andrews become_root code to the main branch. locking.c: Adding Andrews become_root code to the main branch. pipes.c: Fixing the close_file issue. proto.h: The usual. reply.c: Move smb_pass into NTDOMAIN defined code. Fixing the close_file issue. server.c: Fixing the close_file issue. trans2.c: Fixing the close_file issue. uid.c: Adding Andrews become_root code to the main branch. Jeremy (jallison@whistle.com) --- source/include/proto.h | 4 ++- source/locking/locking.c | 45 +++++++++++------------------ source/smbd/ipc.c | 4 +++ source/smbd/pipes.c | 4 +-- source/smbd/reply.c | 26 ++++++++--------- source/smbd/server.c | 16 +++++++---- source/smbd/trans2.c | 4 +-- source/smbd/uid.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 125 insertions(+), 52 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 70a9873d340..85ef0943400 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -776,7 +776,7 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); BOOL check_name(char *name,int cnum); void sync_file(int fnum); -void close_file(int fnum); +void close_file(int fnum, BOOL normal_close); BOOL check_file_sharing(int cnum,char *fname); int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags); @@ -957,6 +957,8 @@ BOOL become_guest(void); BOOL become_user(int cnum, uint16 vuid); BOOL unbecome_user(void ); int smbrun(char *cmd,char *outfile,BOOL shared); +void become_root(BOOL save_dir) ; +void unbecome_root(BOOL restore_dir); /*The following definitions come from username.c */ diff --git a/source/locking/locking.c b/source/locking/locking.c index 04c198afeac..5071121bed0 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -729,10 +729,12 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok if(!share_name(cnum, dev, inode, fname)) return False; + /* we need to do this as root */ + become_root(False); + { int old_umask; BOOL gotlock = False; - unbecome_user(); old_umask = umask(0); /* @@ -801,23 +803,13 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok */ umask(old_umask); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("lock_share_entry: Can't become connected user!\n")); - close(fd); - ret = False; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - close(fd); - ret = False; - } } *ptok = (share_lock_token)fd; + + /* return to our previous privilage level */ + unbecome_root(False); + return ret; } @@ -848,27 +840,22 @@ Force a share file to be deleted. static int delete_share_file( int cnum, char *fname ) { - unbecome_user(); + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + if(unlink(fname) != 0) { DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); } - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + /* return to our previous privilage level */ + unbecome_root(False); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("delete_share_file: Can't become connected user!\n")); - return -1; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - return -1; - } return 0; } diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index c29e8656b17..142f139d260 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1602,6 +1602,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, DEBUG(3,("Setting print name to %s\n",name)); + become_root(True); + for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].open && Files[i].print_file) { @@ -1617,6 +1619,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, string_set(&Files[i].name,name); break; } + + unbecome_root(True); } desc.errcode=NERR_Success; diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index bf53fa84bc2..8c7e6c69c5c 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -147,7 +147,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -155,7 +155,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index dffb6f05bd4..56288df0739 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -479,8 +479,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ if (user[strlen(user) - 1] == '$') { - struct smb_passwd *smb_pass; /* To check if machine account exists */ #ifdef NTDOMAIN + struct smb_passwd *smb_pass; /* To check if machine account exists */ /* PAXX: Ack. We don't want to do this. The workstation trust account with a $ on the end should exist in the local password database @@ -1178,7 +1178,7 @@ int reply_open(char *inbuf,char *outbuf) } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1188,7 +1188,7 @@ int reply_open(char *inbuf,char *outbuf) if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1274,7 +1274,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1282,7 +1282,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1328,7 +1328,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) int i; for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].uid == vuser->uid && Files[i].open) { - close_file(i); + close_file(i,False); } } @@ -2271,7 +2271,7 @@ int reply_close(char *inbuf,char *outbuf) /* try and set the date */ set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum,True); /* We have a cached error */ if(eclass || err) @@ -2318,7 +2318,7 @@ int reply_writeclose(char *inbuf,char *outbuf) set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum,True); DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, @@ -2550,7 +2550,7 @@ int reply_printclose(char *inbuf,char *outbuf) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - close_file(fnum); + close_file(fnum,True); DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); @@ -3187,14 +3187,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum2 = find_free_file(); if (fnum2<0) { - close_file(fnum1); + close_file(fnum1,False); return(False); } open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, ofun,st.st_mode,0,&Access,&action); if (!Files[fnum2].open) { - close_file(fnum1); + close_file(fnum1,False); return(False); } @@ -3205,8 +3205,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, if (st.st_size) ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); - close_file(fnum1); - close_file(fnum2); + close_file(fnum1,False); + close_file(fnum2,False); return(ret == st.st_size); } diff --git a/source/smbd/server.c b/source/smbd/server.c index 1c31f69389d..be24ad7781a 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1361,8 +1361,13 @@ static void check_magic(int fnum,int cnum) /**************************************************************************** close a file - possibly invalidating the read prediction + +If normal_close is 1 then this came from a normal SMBclose (or equivalent) +operation otherwise it came as the result of some other operation such as +the closing of the connection. In the latter case printing and +magic scripts are not run ****************************************************************************/ -void close_file(int fnum) +void close_file(int fnum, BOOL normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; @@ -1399,11 +1404,12 @@ void close_file(int fnum) unlock_share_entry( cnum, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (fs_p->print_file) + if (normal_close && fs_p->print_file) print_file(fnum); /* check for magic scripts */ - check_magic(fnum,cnum); + if (normal_close) + check_magic(fnum,cnum); DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, @@ -1575,7 +1581,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, if (*share_locked && lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, Files[fnum].fd_ptr->inode, token); - close_file(fnum); + close_file(fnum,False); /* Share mode no longer locked. */ *share_locked = False; errno = EACCES; @@ -3847,7 +3853,7 @@ static void close_open_files(int cnum) int i; for (i=0;i<MAX_OPEN_FILES;i++) if( Files[i].cnum == cnum && Files[i].open) { - close_file(i); + close_file(i,False); } } diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index a56df9cb9cc..e484b3b2e1a 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -226,7 +226,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -235,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum,False); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source/smbd/uid.c b/source/smbd/uid.c index 78614a5b5c4..42ade7e4da1 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -481,3 +481,77 @@ int smbrun(char *cmd,char *outfile,BOOL shared) #endif return 1; } + +static struct current_user current_user_saved; +static int become_root_depth; +static pstring become_root_dir; + +/**************************************************************************** +This is used when we need to do a privilaged operation (such as mucking +with share mode files) and temporarily need root access to do it. This +call should always be paired with an unbecome_root() call immediately +after the operation + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void become_root(BOOL save_dir) +{ + if (become_root_depth) { + DEBUG(0,("ERROR: become root depth is non zero\n")); + } + if (save_dir) + GetWd(become_root_dir); + + current_user_saved = current_user; + become_root_depth = 1; + + become_gid(0); + become_uid(0); +} + +/**************************************************************************** +When the privilaged operation is over call this + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void unbecome_root(BOOL restore_dir) +{ + if (become_root_depth != 1) { + DEBUG(0,("ERROR: unbecome root depth is %d\n", + become_root_depth)); + } + + /* we might have done a become_user() while running as root, + if we have then become root again in order to become + non root! */ + if (current_user.uid != 0) { + become_uid(0); + } + + /* restore our gid first */ + if (!become_gid(current_user_saved.gid)) { + DEBUG(0,("ERROR: Failed to restore gid\n")); + exit_server("Failed to restore gid"); + } + +#ifndef NO_SETGROUPS + if (current_user_saved.ngroups > 0) { + if (setgroups(current_user_saved.ngroups, + current_user_saved.groups)<0) + DEBUG(0,("ERROR: setgroups call failed!\n")); + } +#endif + + /* now restore our uid */ + if (!become_uid(current_user_saved.uid)) { + DEBUG(0,("ERROR: Failed to restore uid\n")); + exit_server("Failed to restore uid"); + } + + if (restore_dir) + ChDir(become_root_dir); + + current_user = current_user_saved; + + become_root_depth = 0; +} -- cgit From 4691a94d3c657321d29231f062aed714dfe4ac26 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 16 Oct 1997 00:46:21 +0000 Subject: I got fed up trying to put the tree and list stuff into a subdirectory, so I've started to move them into the main directory. --- source/ubiqx/BinaryTrees.readme | 24 - source/ubiqx/ubi_AVLtree.c | 695 -------------------------- source/ubiqx/ubi_AVLtree.h | 336 ------------- source/ubiqx/ubi_BinTree.c | 1038 --------------------------------------- source/ubiqx/ubi_BinTree.h | 741 ---------------------------- source/ubiqx/ubi_SplayTree.c | 468 ------------------ source/ubiqx/ubi_SplayTree.h | 335 ------------- source/ubiqx/ubi_dLinkList.c | 151 ------ source/ubiqx/ubi_dLinkList.h | 183 ------- source/ubiqx/ubi_sLinkList.c | 102 ---- source/ubiqx/ubi_sLinkList.h | 133 ----- 11 files changed, 4206 deletions(-) delete mode 100644 source/ubiqx/BinaryTrees.readme delete mode 100644 source/ubiqx/ubi_AVLtree.c delete mode 100644 source/ubiqx/ubi_AVLtree.h delete mode 100644 source/ubiqx/ubi_BinTree.c delete mode 100644 source/ubiqx/ubi_BinTree.h delete mode 100644 source/ubiqx/ubi_SplayTree.c delete mode 100644 source/ubiqx/ubi_SplayTree.h delete mode 100644 source/ubiqx/ubi_dLinkList.c delete mode 100644 source/ubiqx/ubi_dLinkList.h delete mode 100644 source/ubiqx/ubi_sLinkList.c delete mode 100644 source/ubiqx/ubi_sLinkList.h diff --git a/source/ubiqx/BinaryTrees.readme b/source/ubiqx/BinaryTrees.readme deleted file mode 100644 index ec99a43d17f..00000000000 --- a/source/ubiqx/BinaryTrees.readme +++ /dev/null @@ -1,24 +0,0 @@ -Short: Binary AVL & Splay trees non-recursive. -Uploader: crh@ubiqx.mn.org (Christopher R. Hertel) -Author: crh@ubiqx.mn.org (Christopher R. Hertel) -Type: dev/c -Version: 2.4. - -Written in C using OOP techniques, these modules provide three forms of -binary tree: Simple (unbalanced) AVL (height-balanced), and Splay. AVL -trees are re-balanced after every insertion or deletion. For each node in -the tree, the difference in height between the left and right subtree is -at most 1. Splay trees use a different approach. Each time a node is -accessed (inserted, deleted, or directly found via a search), the node is -bubbled to the top of the tree. This has the effect of making the tree -'bushier' and placing the most frequently accessed nodes nearer to the -top. - -The functions are non-recursive to limit stack space usage, and can also -be made into a run-time library. The type of tree used is determined by -which header file is included with your program. No other code changes -are necessary. - -Pretty darn fast, too, IMHO. - -Chris Hertel diff --git a/source/ubiqx/ubi_AVLtree.c b/source/ubiqx/ubi_AVLtree.c deleted file mode 100644 index 73b8ece25bc..00000000000 --- a/source/ubiqx/ubi_AVLtree.c +++ /dev/null @@ -1,695 +0,0 @@ -/* ========================================================================== ** - * ubi_AVLtree.c - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module provides an implementation of AVL height balanced binary - * trees. (Adelson-Velskii, Landis 1962) - * - * This file implements the core of the height-balanced (AVL) tree management - * routines. The header file, ubi_AVLtree.h, contains function prototypes - * for all "exported" functions. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_AVLtree.c,v $ - * Revision 1.1 1997/10/10 14:46:36 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.4 1997/07/26 04:36:20 crh - * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied - * on backwards with respect to node deletion. I did some more digging and - * discovered that I was not changing the balance values correctly in the - * single rotation functions. Double rotation was working correctly because - * the formula for changing the balance values is the same for insertion or - * deletion. Not so for single rotation. - * - * I have tested the fix by loading the tree with over 44 thousand names, - * deleting 2,629 of them (all those in which the second character is 'u') - * and then walking the tree recursively to verify that the balance factor of - * each node is correct. Passed. - * - * Thanks Andrew! - * - * Also: - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd - * hoped they would do (see the bottom of the header file). They work now. - * - * Revision 2.3 1997/06/03 04:41:35 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.2 1995/10/03 22:16:01 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:45:59 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/03/05 14:10:51 CRH - * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, - * and so includes all of the changes to that module. In addition, a bug in - * the node deletion process has been fixed. - * - * After rewriting the Locate() function in ubi_BinTree, I decided that it was - * time to overhaul this module. In the process, I discovered a bug related - * to node deletion. To fix the bug, I wrote function Debalance(). A quick - * glance will show that it is very similar to the Rebalance() function. In - * previous versions of this module, I tried to include the functionality of - * Debalance() within Rebalance(), with poor results. - * - * Revision 1.0 93/10/15 22:58:56 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================= ** - */ - -#include "ubi_AVLtree.h" /* Header for THIS module. */ -#include <stdlib.h> /* Standard C definitions, etc. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_AVLtree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/10 14:46:36 $\n\ -\t$Author: crh $\n"; - -/* ========================================================================== ** - * The next set of functions are the AVL balancing routines. There are left - * and right, single and double rotations. The rotation routines handle the - * rotations and reconnect all tree pointers that might get confused by the - * rotations. A pointer to the new subtree root node is returned. - * - * Note that L1 and R1 are identical, except that all the RIGHTs and LEFTs - * are reversed. The same is true for L2 and R2. I'm sure that there is - * a clever way to reduce the amount of code by combining these functions, - * but it might involve additional overhead, and it would probably be a pain - * to read, debug, etc. - * -------------------------------------------------------------------------- ** - */ - -static ubi_avlNodePtr L1( ubi_avlNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Single rotate left. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp; - - tmp = p->Link[RIGHT]; - p->Link[RIGHT] = tmp->Link[LEFT]; - tmp->Link[LEFT] = p; - - tmp->Link[PARENT] = p->Link[PARENT]; - tmp->gender = p->gender; - if(tmp->Link[PARENT]) - (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; - p->Link[PARENT] = tmp; - p->gender = LEFT; - if( p->Link[RIGHT] ) - { - p->Link[RIGHT]->Link[PARENT] = p; - (p->Link[RIGHT])->gender = RIGHT; - } - p->balance -= Normalize( tmp->balance ); - (tmp->balance)--; - return( tmp ); - } /* L1 */ - -static ubi_avlNodePtr R1( ubi_avlNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Single rotate right. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp; - - tmp = p->Link[LEFT]; - p->Link[LEFT] = tmp->Link[RIGHT]; - tmp->Link[RIGHT] = p; - - tmp->Link[PARENT] = p->Link[PARENT]; - tmp->gender = p->gender; - if(tmp->Link[PARENT]) - (tmp->Link[PARENT])->Link[(tmp->gender)] = tmp; - p->Link[PARENT] = tmp; - p->gender = RIGHT; - if(p->Link[LEFT]) - { - p->Link[LEFT]->Link[PARENT] = p; - p->Link[LEFT]->gender = LEFT; - } - p->balance -= Normalize( tmp->balance ); - (tmp->balance)++; - return( tmp ); - } /* R1 */ - -static ubi_avlNodePtr L2( ubi_avlNodePtr tree ) - /* ------------------------------------------------------------------------ ** - * Double rotate left. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp, newroot; - - tmp = tree->Link[RIGHT]; - newroot = tmp->Link[LEFT]; - tmp->Link[LEFT] = newroot->Link[RIGHT]; - newroot->Link[RIGHT] = tmp; - tree->Link[RIGHT] = newroot->Link[LEFT]; - newroot->Link[LEFT] = tree; - - newroot->Link[PARENT] = tree->Link[PARENT]; - newroot->gender = tree->gender; - tree->Link[PARENT] = newroot; - tree->gender = LEFT; - tmp->Link[PARENT] = newroot; - tmp->gender = RIGHT; - - if( tree->Link[RIGHT] ) - { - tree->Link[RIGHT]->Link[PARENT] = tree; - tree->Link[RIGHT]->gender = RIGHT; - } - if( tmp->Link[LEFT] ) - { - tmp->Link[LEFT]->Link[PARENT] = tmp; - tmp->Link[LEFT]->gender = LEFT; - } - if(newroot->Link[PARENT]) - newroot->Link[PARENT]->Link[newroot->gender] = newroot; - - switch( newroot->balance ) - { - case LEFT : - tree->balance = EQUAL; tmp->balance = RIGHT; break; - case EQUAL: - tree->balance = EQUAL; tmp->balance = EQUAL; break; - case RIGHT: - tree->balance = LEFT; tmp->balance = EQUAL; break; - } - newroot->balance = EQUAL; - return( newroot ); - } /* L2 */ - -static ubi_avlNodePtr R2( ubi_avlNodePtr tree ) - /* ------------------------------------------------------------------------ ** - * Double rotate right. - * - * Input: p - Pointer to the root of a tree (possibly a subtree). - * Output: A pointer to the new root of the same subtree (now that node - * p has been moved). - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr tmp, newroot; - - tmp = tree->Link[LEFT]; - newroot = tmp->Link[RIGHT]; - tmp->Link[RIGHT] = newroot->Link[LEFT]; - newroot->Link[LEFT] = tmp; - tree->Link[LEFT] = newroot->Link[RIGHT]; - newroot->Link[RIGHT] = tree; - - newroot->Link[PARENT] = tree->Link[PARENT]; - newroot->gender = tree->gender; - tree->Link[PARENT] = newroot; - tree->gender = RIGHT; - tmp->Link[PARENT] = newroot; - tmp->gender = LEFT; - - if( tree->Link[LEFT] ) - { - tree->Link[LEFT]->Link[PARENT] = tree; - tree->Link[LEFT]->gender = LEFT; - } - if( tmp->Link[RIGHT] ) - { - tmp->Link[RIGHT]->Link[PARENT] = tmp; - tmp->Link[RIGHT]->gender = RIGHT; - } - if(newroot->Link[PARENT]) - newroot->Link[PARENT]->Link[newroot->gender] = newroot; - - switch( newroot->balance ) - { - case LEFT : - tree->balance = RIGHT; tmp->balance = EQUAL; break; - case EQUAL : - tree->balance = EQUAL; tmp->balance = EQUAL; break; - case RIGHT : - tree->balance = EQUAL; tmp->balance = LEFT; break; - } - newroot->balance = EQUAL; - return( newroot ); - } /* R2 */ - - -static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR ) - /* ------------------------------------------------------------------------ ** - * Adjust the balance value at node *p. If necessary, rotate the subtree - * rooted at p. - * - * Input: p - A pointer to the node to be adjusted. One of the - * subtrees of this node has changed height, so the - * balance value at this node must be adjusted, possibly - * by rotating the tree at this node. - * LorR - Indicates the TALLER subtree. - * - * Output: A pointer to the (possibly new) root node of the subtree. - * - * Notes: This function may be called after a node has been added *or* - * deleted, so LorR indicates the TALLER subtree. - * ------------------------------------------------------------------------ ** - */ - { - if( p->balance != LorR ) - p->balance += Normalize(LorR); - else - { - char tallerbal; /* Balance value of the root of the taller subtree of p. */ - - tallerbal = p->Link[LorR]->balance; - if( ( EQUAL == tallerbal ) || ( p->balance == tallerbal ) ) - p = ( (LEFT==LorR) ? R1(p) : L1(p) ); /* single rotation */ - else - p = ( (LEFT==LorR) ? R2(p) : L2(p) ); /* double rotation */ - } - return( p ); - } /* Adjust */ - -static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root, - ubi_avlNodePtr subtree, - char LorR ) - /* ------------------------------------------------------------------------ ** - * Rebalance the tree following an insertion. - * - * Input: Root - A pointer to the root node of the whole tree. - * subtree - A pointer to the node that has just gained a new - * child. - * LorR - Gender of the child that has just been gained. - * - * Output: A pointer to the (possibly new) root of the AVL tree. - * Rebalancing the tree moves nodes around a bit, so the node - * that *was* the root, may not be the root when we're finished. - * - * Notes: Rebalance() must walk up the tree from where we are (which is - * where the latest change occurred), rebalancing the subtrees - * along the way. The rebalancing operation can stop if the - * change at the current subtree root won't affect the rest of - * the tree. In the case of an addition, if a subtree root's - * balance becomes EQUAL, then we know that the height of that - * subtree has not changed, so we can exit. - * ------------------------------------------------------------------------ ** - */ - { - while( subtree ) - { - subtree = Adjust( subtree, LorR ); - if( PARENT == subtree->gender ) - return( subtree ); - if( EQUAL == subtree->balance ) - return( Root ); - LorR = subtree->gender; - subtree = subtree->Link[PARENT]; - } - return( Root ); - } /* Rebalance */ - -static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root, - ubi_avlNodePtr subtree, - char LorR ) - /* ------------------------------------------------------------------------ ** - * Rebalance the tree following a deletion. - * - * Input: Root - A pointer to the root node of the whole tree. - * subtree - A pointer to the node who's child has just "left the - * nest". - * LorR - Gender of the child that left. - * - * Output: A pointer to the (possibly new) root of the AVL tree. - * Rebalancing the tree moves nodes around a bit, so the node - * that *was* the root, may not be the root when we're finished. - * - * Notes: Debalance() is subtly different from Rebalance() (above) in - * two respects. - * * When it calls Adjust(), it passes the *opposite* of LorR. - * This is because LorR, as passed into Debalance() indicates - * the shorter subtree. As we move up the tree, LorR is - * assigned the gender of the node that we are leaving (i.e., - * the subtree that we just rebalanced). - * * We know that a subtree has not changed height if the - * balance becomes LEFT or RIGHT. This is the *opposite* of - * what happens in Rebalance(). - * ------------------------------------------------------------------------ ** - */ - { - while( subtree ) - { - subtree = Adjust( subtree, RevWay(LorR) ); - if( PARENT == subtree->gender ) - return( subtree ); - if( EQUAL != subtree->balance ) - return( Root ); - LorR = subtree->gender; - subtree = subtree->Link[PARENT]; - } - return( Root ); - } /* Debalance */ - - -/* -------------------------------------------------------------------------- ** - * The next two functions are used for general tree manipulation. They are - * each slightly different from their ubi_BinTree counterparts. - * -------------------------------------------------------------------------- ** - */ - -static void ReplaceNode( ubi_avlNodePtr *parent, - ubi_avlNodePtr oldnode, - ubi_avlNodePtr newnode ) - /* ------------------------------------------------------------------------ ** - * Remove node oldnode from the tree, replacing it with node newnode. - * - * Input: - * parent - A pointer to he parent pointer of the node to be - * replaced. <parent> may point to the Link[] field of - * a parent node, or it may indicate the root pointer at - * the top of the tree. - * oldnode - A pointer to the node that is to be replaced. - * newnode - A pointer to the node that is to be installed in the - * place of <*oldnode>. - * - * Notes: Don't forget to free oldnode. - * The only difference between this function and the ubi_bt - * version is that the node size is sizeof( ubi_avlNode ), not - * sizeof( ubi_btNode ). - * ------------------------------------------------------------------------ ** - */ - { - register int i; - register int avlNodeSize = sizeof( ubi_avlNode ); - - for( i = 0; i < avlNodeSize; i++ ) - ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - (*parent) = newnode; - - if(oldnode->Link[LEFT ] ) - (oldnode->Link[LEFT ])->Link[PARENT] = newnode; - if(oldnode->Link[RIGHT] ) - (oldnode->Link[RIGHT])->Link[PARENT] = newnode; - } /* ReplaceNode */ - -static void SwapNodes( ubi_btRootPtr RootPtr, - ubi_avlNodePtr Node1, - ubi_avlNodePtr Node2 ) - /* ------------------------------------------------------------------------ ** - * This function swaps two nodes in the tree. Node1 will take the place of - * Node2, and Node2 will fill in the space left vacant by Node 1. - * - * Input: - * RootPtr - pointer to the tree header structure for this tree. - * Node1 - \ - * > These are the two nodes which are to be swapped. - * Node2 - / - * - * Notes: - * This function does a three step swap, using a dummy node as a place - * holder. This function is used by ubi_avlRemove(). - * The only difference between this function and its ubi_bt counterpart - * is that the nodes are ubi_avlNodes, not ubi_btNodes. - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr *Parent; - ubi_avlNode dummy; - ubi_avlNodePtr dummy_p = &dummy; - - if( Node1->Link[PARENT] ) - Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, Node1, dummy_p ); - - if( Node2->Link[PARENT] ) - Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, Node2, Node1 ); - - if( dummy_p->Link[PARENT] ) - Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); - else - Parent = (ubi_avlNodePtr *)&(RootPtr->root); - ReplaceNode( Parent, dummy_p, Node2 ); - } /* SwapNodes */ - - -/* ========================================================================== ** - * Public, exported (ie. not static-ly declared) functions... - * -------------------------------------------------------------------------- ** - */ - -ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: NodePtr - pointer to a ubi_btNode structure to be - * initialized. - * Output: a pointer to the initialized ubi_avlNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - { - (void)ubi_btInitNode( (ubi_btNodePtr)NodePtr ); - NodePtr->balance = EQUAL; - return( NodePtr ); - } /* ubi_avlInitNode */ - -ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, - ubi_avlNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_avlNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to - * the tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_avlNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_avlNodePtr OtherP; - - if( !(OldNode) ) OldNode = &OtherP; - if( ubi_btInsert( RootPtr, - (ubi_btNodePtr)NewNode, - ItemPtr, - (ubi_btNodePtr *)OldNode ) ) - { - if( (*OldNode) ) - NewNode->balance = (*OldNode)->balance; - else - { - NewNode->balance = EQUAL; - RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_avlNodePtr)RootPtr->root, - NewNode->Link[PARENT], - NewNode->gender ); - } - return( ubi_trTRUE ); - } - return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ - } /* ubi_avlInsert */ - -ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, - ubi_avlNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree, after which the - * tree is rebalanced. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, - *parentp; - - /* if the node has both left and right subtrees, then we have to swap - * it with another node. - */ - if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) - SwapNodes( RootPtr, DeadNode, ubi_trPrev( DeadNode ) ); - - /* The parent of the node to be deleted may be another node, or it may be - * the root of the tree. Since we're not sure, it's best just to have - * a pointer to the parent pointer, whatever it is. - */ - if( DeadNode->Link[PARENT] ) - parentp = (ubi_btNodePtr *) - &((DeadNode->Link[PARENT])->Link[(DeadNode->gender)]); - else - parentp = &( RootPtr->root ); - - /* Now link the parent to the only grand-child. Patch up the gender and - * such, and rebalance. - */ - if( EQUAL == DeadNode->balance ) - (*parentp) = NULL; - else - { - p = (ubi_btNodePtr)(DeadNode->Link[(DeadNode->balance)]); - p->Link[PARENT] = (ubi_btNodePtr)DeadNode->Link[PARENT]; - p->gender = DeadNode->gender; - (*parentp) = p; - } - RootPtr->root = (ubi_btNodePtr)Debalance( (ubi_avlNodePtr)RootPtr->root, - DeadNode->Link[PARENT], - DeadNode->gender ); - - (RootPtr->count)--; - return( DeadNode ); - } /* ubi_avlRemove */ - -int ubi_avlModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); - return( 1 ); - } - return( 0 ); - } /* ubi_avlModuleID */ - -/* ============================== The End ============================== */ diff --git a/source/ubiqx/ubi_AVLtree.h b/source/ubiqx/ubi_AVLtree.h deleted file mode 100644 index be6fe032126..00000000000 --- a/source/ubiqx/ubi_AVLtree.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef ubi_AVLtree_H -#define ubi_AVLtree_H -/* ========================================================================== ** - * ubi_AVLtree.h - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module provides an implementation of AVL height balanced binary - * trees. (Adelson-Velskii, Landis 1962) - * - * This header file contains the basic AVL structure and pointer typedefs - * as well as the prototypes needed to access the functions in the AVL - * module ubi_AVLtree. The .c file implements the low-level height balancing - * routines that manage the AVL tree, plus all of the basic primops for - * adding, searching for, and deleting nodes. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * $Log: ubi_AVLtree.h,v $ - * Revision 1.1 1997/10/10 14:46:37 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.4 1997/07/26 04:36:23 crh - * Andrew Leppard, aka "Grazgur", discovered that I still had my brains tied - * on backwards with respect to node deletion. I did some more digging and - * discovered that I was not changing the balance values correctly in the - * single rotation functions. Double rotation was working correctly because - * the formula for changing the balance values is the same for insertion or - * deletion. Not so for single rotation. - * - * I have tested the fix by loading the tree with over 44 thousand names, - * deleting 2,629 of them (all those in which the second character is 'u') - * and then walking the tree recursively to verify that the balance factor of - * each node is correct. Passed. - * - * Thanks Andrew! - * - * Also: - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * + Rewrote the ubi_tr<func> macros because they weren't doing what I'd - * hoped they would do (see the bottom of the header file). They work now. - * - * Revision 2.3 1997/06/03 05:22:07 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.2 1995/10/03 22:15:47 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:46:44 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/03/05 14:11:22 CRH - * This revision of ubi_AVLtree coincides with revision 2.0 of ubi_BinTree, - * and so includes all of the changes to that module. In addition, a bug in - * the node deletion process has been fixed. - * - * After rewriting the Locate() function in ubi_BinTree, I decided that it was - * time to overhaul this module. In the process, I discovered a bug related - * to node deletion. To fix the bug, I wrote function Debalance(). A quick - * glance will show that it is very similar to the Rebalance() function. In - * previous versions of this module, I tried to include the functionality of - * Debalance() within Rebalance(), with poor results. - * - * Revision 1.0 93/10/15 22:58:48 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - May, 1990 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================= ** - */ - -#include "ubi_BinTree.h" /* Base erg binary tree support. */ - -/* ------------------------------------------------------------------------- ** - * AVL Tree Node Structure: This structure defines the basic elements of - * the AVL tree nodes. In general you *SHOULD NOT PLAY WITH THESE - * FIELDS*! But, of course, I have to put the structure into this - * header so that you can use the structure as a building block. - * - * The fields are as follows: - * Link - An array of pointers. These pointers are manipulated by the - * BT and AVL routines, and indicate the left and right child - * nodes, plus the parent node. By keeping track of the parent - * pointer, we avoid the need for recursive routines or hand- - * tooled stacks to keep track of our path back to the root. - * The use of these pointers is subject to change without - * notice. - * gender - For tree rebalancing purposes, it is necessary that each node - * know whether it is the left or right child of its parent, or - * if it is the root. This information is stored in this field. - * balance - This field is also needed for AVL balancing purposes. It - * indicates which subtree of the current node is longer, or if - * the subtrees are, in fact, balanced with respect to each - * other. - * ------------------------------------------------------------------------- ** - */ - -typedef struct ubi_avlNodeStruct { - struct ubi_avlNodeStruct - *Link[3]; /* Normal Binary Tree Node type. */ - char gender; /* The node is either the RIGHT or LEFT child of its */ - /* parent, or is the root node. */ - char balance; /* In an AVL tree, each node is the root of a subtree */ - /* that may be balanced, or be one node longer to the */ - /* right or left. This field keeps track of the */ - /* balance value of each node. */ - } ubi_avlNode; /* Typedef'd name for an avl tree node. */ - -typedef ubi_avlNode *ubi_avlNodePtr; /* a Pointer to an AVL node */ - -/* -------------------------------------------------------------------------- ** - * Function prototypes. - * -------------------------------------------------------------------------- ** - */ - -ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: NodePtr - a pointer to a ubi_btNode structure to be - * initialized. - * Output: a pointer to the initialized ubi_avlNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr, - ubi_avlNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_avlNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to - * the tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_avlNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr, - ubi_avlNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree, after which the - * tree is rebalanced. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -int ubi_avlModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_avl... or ubi_bt, use ubi_tr... and select the tree - * type by including the appropriate module header. - */ - -#undef ubi_trNode -#undef ubi_trNodePtr -#define ubi_trNode ubi_avlNode -#define ubi_trNodePtr ubi_avlNodePtr - -#undef ubi_trInitNode -#define ubi_trInitNode( Np ) ubi_avlInitNode( (ubi_avlNodePtr)(Np) ) - -#undef ubi_trInsert -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_avlNodePtr *)(On) ) - -#undef ubi_trRemove -#define ubi_trRemove( Rp, Dn ) \ - ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Dn) ) - -#undef ubi_trLocate -#define ubi_trLocate( Rp, Ip, Op ) \ - (ubi_avlNodePtr)ubi_btLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#undef ubi_trFind -#define ubi_trFind( Rp, Ip ) \ - (ubi_avlNodePtr)ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#undef ubi_trNext -#define ubi_trNext( P ) (ubi_avlNodePtr)ubi_btNext( (ubi_btNodePtr)(P) ) - -#undef ubi_trPrev -#define ubi_trPrev( P ) (ubi_avlNodePtr)ubi_btPrev( (ubi_btNodePtr)(P) ) - -#undef ubi_trFirst -#define ubi_trFirst( P ) (ubi_avlNodePtr)ubi_btFirst( (ubi_btNodePtr)(P) ) - -#undef ubi_trLast -#define ubi_trLast( P ) (ubi_avlNodePtr)ubi_btLast( (ubi_btNodePtr)(P) ) - -#undef ubi_trFirstOf -#define ubi_trFirstOf( Rp, Ip, P ) \ - (ubi_avlNodePtr)ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#undef ubi_trLastOf -#define ubi_trLastOf( Rp, Ip, P ) \ - (ubi_avlNodePtr)ubi_btLastOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#undef ubi_trLeafNode -#define ubi_trLeafNode( Nd ) \ - (ubi_avlNodePtr)ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) - -#undef ubi_trModuleID -#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l ) - - -/* =========================== End ubi_AVLtree.h =========================== */ -#endif /* ubi_AVLtree_H */ diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c deleted file mode 100644 index dc72f9bad3d..00000000000 --- a/source/ubiqx/ubi_BinTree.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* ========================================================================== ** - * ubi_BinTree.c - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height - * balancing, no restructuring. Still, a good tool for creating short, low- - * overhead sorted lists of things that need to be found in a hurry. - * - * In addition, this module provides a good basis for creating other types - * of binary tree handling modules. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_BinTree.c,v $ - * Revision 1.1 1997/10/10 14:46:38 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.4 1997/07/26 04:11:10 crh - * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE - * and ubi_trFALSE. - * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. - * + There used to be something called "ubi_TypeDefs.h". I got rid of it. - * + Added function ubi_btLeafNode(). - * - * Revision 2.3 1997/06/03 05:16:17 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. - * Also changed the interface to function InitTree(). See the comments - * for this function for more information. - * - * Revision 2.2 1995/10/03 22:00:07 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:37:10 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:00:17 CRH - * Revision 2.0 of this program includes the following changes: - * - * 1) A fix to a major typo in the RepaceNode() function. - * 2) The addition of the static function Border(). - * 3) The addition of the public functions FirstOf() and LastOf(), which - * use Border(). These functions are used with trees that allow - * duplicate keys. - * 4) A complete rewrite of the Locate() function. Locate() now accepts - * a "comparison" operator. - * 5) Overall enhancements to both code and comments. - * - * I decided to give this a new major rev number because the interface has - * changed. In particular, there are two new functions, and changes to the - * Locate() function. - * - * Revision 1.0 93/10/15 22:44:59 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================== ** - */ - -#include "ubi_BinTree.h" /* Header for this module */ -#include <stdlib.h> /* Standard C definitions. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_BinTree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/10 14:46:38 $\n\ -\t$Author: crh $\n"; - -/* ========================================================================== ** - * Internal (private) functions. - */ - -static ubi_btNodePtr qFind( ubi_btCompFunc cmp, - ubi_btItemPtr FindMe, - register ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for a node - * matching a specific key. It is called "qFind()" because it is - * faster that TreeFind (below). - * - * Input: - * cmp - a pointer to the tree's comparison function. - * FindMe - a pointer to the key value for which to search. - * p - a pointer to the starting point of the search. <p> - * is considered to be the root of a subtree, and only - * the subtree will be searched. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. - * ------------------------------------------------------------------------ ** - */ - { - char tmp; - - while( p && (( tmp = AbNormal((*cmp)(FindMe, p)) ) != EQUAL) ) - p = p->Link[tmp]; - - return( p ); - } /* qFind */ - -static ubi_btNodePtr TreeFind( ubi_btItemPtr findme, - ubi_btNodePtr p, - ubi_btNodePtr *parentp, - char *gender, - ubi_btCompFunc CmpFunc ) - /* ------------------------------------------------------------------------ ** - * TreeFind() searches a tree for a given value (findme). It will return a - * pointer to the target node, if found, or NULL if the target node was not - * found. - * - * TreeFind() also returns, via parameters, a pointer to the parent of the - * target node, and a LEFT or RIGHT value indicating which child of the - * parent is the target node. *If the target is not found*, then these - * values indicate the place at which the target *should be found*. This - * is useful when inserting a new node into a tree or searching for nodes - * "near" the target node. - * - * The parameters are: - * - * findme - is a pointer to the key information to be searched for. - * p - points to the root of the tree to be searched. - * parentp - will return a pointer to a pointer to the !parent! of the - * target node, which can be especially usefull if the target - * was not found. - * gender - returns LEFT or RIGHT to indicate which child of *parentp - * was last searched. - * CmpFunc - points to the comparison function. - * - * This function is called by ubi_btLocate() and ubi_btInsert(). - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr tmp_p = p; - ubi_btNodePtr tmp_pp = NULL; - char tmp_sex = EQUAL; - char tmp_cmp; - - while( tmp_p && (EQUAL != (tmp_cmp = AbNormal((*CmpFunc)(findme, tmp_p)))) ) - { - tmp_pp = tmp_p; /* Keep track of previous node. */ - tmp_sex = tmp_cmp; /* Keep track of sex of child. */ - tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */ - } - *parentp = tmp_pp; /* Return results. */ - *gender = tmp_sex; - return( tmp_p ); - } /* TreeFind */ - -static void ReplaceNode( ubi_btNodePtr *parent, - ubi_btNodePtr oldnode, - ubi_btNodePtr newnode ) - /* ------------------------------------------------------------------ * - * Remove node oldnode from the tree, replacing it with node newnode. - * - * Input: - * parent - A pointer to he parent pointer of the node to be - * replaced. <parent> may point to the Link[] field of - * a parent node, or it may indicate the root pointer at - * the top of the tree. - * oldnode - A pointer to the node that is to be replaced. - * newnode - A pointer to the node that is to be installed in the - * place of <*oldnode>. - * - * Notes: Don't forget to free oldnode. - * Also, this function used to have a really nasty typo - * bug. "oldnode" and "newnode" were swapped in the line - * that now reads: - * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - * Bleah! - * ------------------------------------------------------------------ * - */ - { - register int i; - register int btNodeSize = sizeof( ubi_btNode ); - - for( i = 0; i < btNodeSize; i++ ) /* Copy node internals to new node. */ - ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i]; - (*parent) = newnode; /* Old node's parent points to new child. */ - /* Now tell the children about their new step-parent. */ - if( oldnode->Link[LEFT ] ) (oldnode->Link[LEFT ])->Link[PARENT] = newnode; - if( oldnode->Link[RIGHT] ) (oldnode->Link[RIGHT])->Link[PARENT] = newnode; - } /* ReplaceNode */ - -static void SwapNodes( ubi_btRootPtr RootPtr, - ubi_btNodePtr Node1, - ubi_btNodePtr Node2 ) - /* ------------------------------------------------------------------------ ** - * This function swaps two nodes in the tree. Node1 will take the place of - * Node2, and Node2 will fill in the space left vacant by Node 1. - * - * Input: - * RootPtr - pointer to the tree header structure for this tree. - * Node1 - \ - * > These are the two nodes which are to be swapped. - * Node2 - / - * - * Notes: - * This function does a three step swap, using a dummy node as a place - * holder. This function is used by ubi_btRemove(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr *Parent; - ubi_btNode dummy; - ubi_btNodePtr dummy_p = &dummy; - - /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */ - if( Node1->Link[PARENT] ) - Parent = &((Node1->Link[PARENT])->Link[Node1->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, Node1, dummy_p ); - - /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */ - if( Node2->Link[PARENT] ) - Parent = &((Node2->Link[PARENT])->Link[Node2->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, Node2, Node1 ); - - /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */ - if( dummy_p->Link[PARENT] ) - Parent = &((dummy_p->Link[PARENT])->Link[dummy_p->gender]); - else - Parent = &(RootPtr->root); - ReplaceNode( Parent, dummy_p, Node2 ); - } /* SwapNodes */ - -/* -------------------------------------------------------------------------- ** - * These routines allow you to walk through the tree, forwards or backwards. - */ - -static ubi_btNodePtr SubSlide( register ubi_btNodePtr P, - register char whichway ) - /* ------------------------------------------------------------------------ ** - * Slide down the side of a subtree. - * - * Given a starting node, this function returns a pointer to the LEFT-, or - * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root. - * - * Input: P - a pointer to a starting place. - * whichway - the direction (LEFT, RIGHT, or PARENT) in which to - * travel. - * Output: A pointer to a node that is either the root, or has no - * whichway-th child but is within the subtree of P. Note that - * the return value may be the same as P. The return value *will - * be* NULL if P is NULL. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr Q = NULL; - - while( P ) - { - Q = P; - P = P->Link[ whichway ]; - } - return( Q ); - } /* SubSlide */ - -static ubi_btNodePtr Neighbor( register ubi_btNodePtr P, - register char whichway ) - /* ------------------------------------------------------------------------ ** - * Given starting point p, return the (key order) next or preceeding node - * in the tree. - * - * Input: P - Pointer to our starting place node. - * whichway - the direction in which to travel to find the - * neighbor, i.e., the RIGHT neighbor or the LEFT - * neighbor. - * - * Output: A pointer to the neighboring node, or NULL if P was NULL. - * - * Notes: If whichway is PARENT, the results are unpredictable. - * ------------------------------------------------------------------------ ** - */ - { - if( P ) - { - if( P->Link[ whichway ] ) - return( SubSlide( P->Link[ whichway ], (char)RevWay(whichway) ) ); - else - while( P->Link[ PARENT ] ) - { - if( (P->Link[ PARENT ])->Link[ whichway ] == P ) - P = P->Link[ PARENT ]; - else - return( P->Link[ PARENT ] ); - } - } - return( NULL ); - } /* Neighbor */ - -static ubi_btNodePtr Border( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_btNodePtr p, - char whichway ) - /* ------------------------------------------------------------------------ ** - * Given starting point p, which has a key value equal to *FindMe, locate - * the first (index order) node with the same key value. - * - * This function is useful in trees that have can have duplicate keys. - * For example, consider the following tree: - * Tree Traversal - * 2 If <p> points to the root and <whichway> is RIGHT, 3 - * / \ then the return value will be a pointer to the / \ - * 2 2 RIGHT child of the root node. The tree on 2 5 - * / / \ the right shows the order of traversal. / / \ - * 1 2 3 1 4 6 - * - * Input: RootPtr - Pointer to the tree root structure. - * FindMe - Key value for comparisons. - * p - Pointer to the starting-point node. - * whichway - the direction in which to travel to find the - * neighbor, i.e., the RIGHT neighbor or the LEFT - * neighbor. - * - * Output: A pointer to the first (index, or "traversal", order) node with - * a Key value that matches *FindMe. - * - * Notes: If whichway is PARENT, or if the tree does not allow duplicate - * keys, this function will return <p>. - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr q; - - /* Exit if there's nothing that can be done. */ - if( !Dups_OK( RootPtr ) || (PARENT == whichway) ) - return( p ); - - /* First, if needed, move up the tree. We need to get to the root of the - * subtree that contains all of the matching nodes. - */ - q = p->Link[PARENT]; - while( q && (EQUAL == AbNormal( (*(RootPtr->cmp))(FindMe, q) )) ) - { - p = q; - q = p->Link[PARENT]; - } - - /* Next, move back down in the "whichway" direction. */ - q = p->Link[whichway]; - while( q ) - { - if( q = qFind( RootPtr->cmp, FindMe, q ) ) - { - p = q; - q = p->Link[whichway]; - } - } - return( p ); - } /* Border */ - - -/* ========================================================================== ** - * Exported utilities. - */ - -long ubi_btSgn( register long x ) - /* ------------------------------------------------------------------------ ** - * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. - * - * Input: x - a signed long integer value. - * - * Output: the "sign" of x, represented as follows: - * -1 == negative - * 0 == zero (no sign) - * 1 == positive - * - * Note: This utility is provided in order to facilitate the conversion - * of C comparison function return values into BinTree direction - * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the - * AbNormal() conversion macro! - * - * ------------------------------------------------------------------------ ** - */ - { - return( (x)?((x>0)?(1):(-1)):(0) ); - } /* ubi_btSgn */ - -ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: a pointer to a ubi_btNode structure to be initialized. - * Output: a pointer to the initialized ubi_btNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - { - NodePtr->Link[ LEFT ] = NULL; - NodePtr->Link[ PARENT ] = NULL; - NodePtr->Link[ RIGHT ] = NULL; - NodePtr->gender = EQUAL; - return( NodePtr ); - } /* ubi_btInitNode */ - -ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, - ubi_btCompFunc CompFunc, - unsigned char Flags ) - /* ------------------------------------------------------------------------ ** - * Initialize the fields of a Tree Root header structure. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure to be - * initialized. - * CompFunc - a pointer to a comparison function that will be used - * whenever nodes in the tree must be compared against - * outside values. - * Flags - One bytes worth of flags. Flags include - * ubi_trOVERWRITE and ubi_trDUPKEY. See the header - * file for more info. - * - * Output: a pointer to the initialized ubi_btRoot structure (ie. the - * same value as RootPtr). - * - * Note: The interface to this function has changed from that of - * previous versions. The <Flags> parameter replaces two - * boolean parameters that had the same basic effect. - * - * ------------------------------------------------------------------------ ** - */ - { - if( RootPtr ) - { - RootPtr->root = NULL; - RootPtr->count = 0L; - RootPtr->cmp = CompFunc; - RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags; - } /* There are only two supported flags, and they are - * mutually exclusive. ubi_trDUPKEY takes precedence - * over ubi_trOVERWRITE. - */ - return( RootPtr ); - } /* ubi_btInitTree */ - -ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr OtherP, - parent = NULL; - char tmp; - - if( !(OldNode) ) /* If they didn't give us a pointer, supply our own. */ - OldNode = &OtherP; - - (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ - - /* Find a place for the new node. */ - *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); - - /* Now add the node to the tree... */ - if (!(*OldNode)) /* The easy one: we have a space for a new node! */ - { - if (!(parent)) - RootPtr->root = NewNode; - else - { - parent->Link[tmp] = NewNode; - NewNode->Link[PARENT] = parent; - NewNode->gender = tmp; - } - (RootPtr->count)++; - return( ubi_trTRUE ); - } - - /* If we reach this point, we know that a duplicate node exists. This - * section adds the node to the tree if duplicate keys are allowed. - */ - if( Dups_OK(RootPtr) ) /* Key exists, add duplicate */ - { - ubi_btNodePtr q; - - tmp = RIGHT; - q = (*OldNode); - *OldNode = NULL; - while( q ) - { - parent = q; - if( tmp == EQUAL ) tmp = RIGHT; - q = q->Link[tmp]; - if ( q ) - tmp = AbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); - } - parent->Link[tmp] = NewNode; - NewNode->Link[PARENT] = parent; - NewNode->gender = tmp; - (RootPtr->count)++; - return( ubi_trTRUE ); - } - - /* If we get to *this* point, we know that we are not allowed to have - * duplicate nodes, but our node keys match, so... may we replace the - * old one? - */ - if( Ovwt_OK(RootPtr) ) /* Key exists, we replace */ - { - if (!(parent)) - ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); - else - ReplaceNode( &(parent->Link[(*OldNode)->gender]), *OldNode, NewNode ); - return( ubi_trTRUE ); - } - - return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ - } /* ubi_btInsert */ - -ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, - ubi_btNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, - *parentp; - char tmp; - - /* if the node has both left and right subtrees, then we have to swap - * it with another node. The other node we choose will be the Prev()ious - * node, which is garunteed to have no RIGHT child. - */ - if( (DeadNode->Link[LEFT]) && (DeadNode->Link[RIGHT]) ) - SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) ); - - /* The parent of the node to be deleted may be another node, or it may be - * the root of the tree. Since we're not sure, it's best just to have - * a pointer to the parent pointer, whatever it is. - */ - if (DeadNode->Link[PARENT]) - parentp = &((DeadNode->Link[PARENT])->Link[DeadNode->gender]); - else - parentp = &( RootPtr->root ); - - /* Now link the parent to the only grand-child and patch up the gender. */ - tmp = ((DeadNode->Link[LEFT])?LEFT:RIGHT); - - p = (DeadNode->Link[tmp]); - if( p ) - { - p->Link[PARENT] = DeadNode->Link[PARENT]; - p->gender = DeadNode->gender; - } - (*parentp) = p; - - /* Finished, reduce the node count and return. */ - (RootPtr->count)--; - return( DeadNode ); - } /* ubi_btRemove */ - -ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ) - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - { - register ubi_btNodePtr p; - ubi_btNodePtr parent; - char whichkid; - - /* Start by searching for a matching node. */ - p = TreeFind( FindMe, - RootPtr->root, - &parent, - &whichkid, - RootPtr->cmp ); - - if( p ) /* If we have found a match, we can resolve as follows: */ - { - switch( CompOp ) - { - case ubi_trLT: /* It's just a jump to the left... */ - p = Border( RootPtr, FindMe, p, LEFT ); - return( Neighbor( p, LEFT ) ); - case ubi_trGT: /* ...and then a jump to the right. */ - p = Border( RootPtr, FindMe, p, RIGHT ); - return( Neighbor( p, RIGHT ) ); - } - p = Border( RootPtr, FindMe, p, LEFT ); - return( p ); - } - - /* Else, no match. */ - if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ - return( NULL ); /* ...forget it. */ - - /* We can still return a valid result for GT, GE, LE, and LT. - * <parent> points to a node with a value that is either just before or - * just after the target value. - * Remaining possibilities are LT and GT (including LE & GE). - */ - if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) - return( (LEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); - else - return( (RIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); - } /* ubi_btLocate */ - -ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_btLocate(). - * ------------------------------------------------------------------------ ** - */ - { - return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) ); - } /* ubi_btFind */ - -ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Next node in the - * tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "next" node in the tree, or NULL if P pointed - * to the "last" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - { - return( Neighbor( P, RIGHT ) ); - } /* ubi_btNext */ - -ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Previous node in - * the tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "previous" node in the tree, or NULL if P - * pointed to the "first" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - { - return( Neighbor( P, LEFT ) ); - } /* ubi_btPrev */ - -ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) First node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "first" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - { - return( SubSlide( P, LEFT ) ); - } /* ubi_btFirst */ - -ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ) - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Last node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "last" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - { - return( SubSlide( P, RIGHT ) ); - } /* ubi_btLast */ - -ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the first (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the first node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - { - /* If our starting point is invalid, return NULL. */ - if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) - return( NULL ); - return( Border( RootPtr, MatchMe, p, LEFT ) ); - } /* ubi_btFirstOf */ - -ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the last (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the last node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - { - /* If our starting point is invalid, return NULL. */ - if( !p || AbNormal( (*(RootPtr->cmp))( MatchMe, p ) != EQUAL ) ) - return( NULL ); - return( Border( RootPtr, MatchMe, p, RIGHT ) ); - } /* ubi_btLastOf */ - -ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, - ubi_btActionRtn EachNode, - void *UserData ) - /* ------------------------------------------------------------------------ ** - * Traverse a tree in sorted order (non-recursively). At each node, call - * (*EachNode)(), passing a pointer to the current node, and UserData as the - * second parameter. - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the tree to be traversed. - * EachNode - a pointer to a function to be called at each node - * as the node is visited. - * UserData - a generic pointer that may point to anything that - * you choose. - * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - if( !(p = ubi_btFirst( RootPtr->root )) ) return( ubi_trFALSE ); - - while( p ) - { - EachNode( p, UserData ); - p = ubi_btNext( p ); - } - return( ubi_trTRUE ); - } /* ubi_btTraverse */ - -ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, - ubi_btKillNodeRtn FreeNode ) - /* ------------------------------------------------------------------------ ** - * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot - * structure. Note that this function will return FALSE if either parameter - * is NULL. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the root of the tree to delete. - * FreeNode - a function that will be called for each node in the - * tree to deallocate the memory used by the node. - * - * Output: A boolean value. FALSE if either input parameter was NULL, else - * TRUE. - * - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p, q; - - if( !(RootPtr) || !(FreeNode) ) - return( ubi_trFALSE ); - - p = ubi_btFirst( RootPtr->root ); - while( p ) - { - q = p; - while( q->Link[RIGHT] ) - q = SubSlide( q->Link[RIGHT], LEFT ); - p = q->Link[PARENT]; - if( p ) - p->Link[ ((p->Link[LEFT] == q)?LEFT:RIGHT) ] = NULL; - FreeNode((void *)q); - } - - (void)ubi_btInitTree( RootPtr, - RootPtr->cmp, - RootPtr->flags ); - return( ubi_trTRUE ); - } /* ubi_btKillTree */ - -ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ) - /* ------------------------------------------------------------------------ ** - * Returns a pointer to a leaf node. - * - * Input: leader - Pointer to a node at which to start the descent. - * - * Output: A pointer to a leaf node selected in a somewhat arbitrary - * manner. - * - * Notes: I wrote this function because I was using splay trees as a - * database cache. The cache had a maximum size on it, and I - * needed a way of choosing a node to sacrifice if the cache - * became full. In a splay tree, less recently accessed nodes - * tend toward the bottom of the tree, meaning that leaf nodes - * are good candidates for removal. (I really can't think of - * any other reason to use this function.) - * + In a simple binary tree or an AVL tree, the most recently - * added nodes tend to be nearer the bottom, making this a *bad* - * way to choose which node to remove from the cache. - * + Randomizing the traversal order is probably a good idea. You - * can improve the randomization of leaf node selection by passing - * in pointers to nodes other than the root node each time. A - * pointer to any node in the tree will do. Of course, if you - * pass a pointer to a leaf node you'll get the same thing back. - * - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr follower = NULL; - int whichway = LEFT; - - while( NULL != leader ) - { - follower = leader; - leader = follower->Link[ whichway ]; - if( NULL == leader ) - { - whichway = RevWay( whichway ); - leader = follower->Link[ whichway ]; - } - } - - return( follower ); - } /* ubi_btLeafNode */ - -int ubi_btModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - list[1] = NULL; - return( 1 ); - } - return( 0 ); - } /* ubi_btModuleID */ - - -/* ========================================================================== */ diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h deleted file mode 100644 index b4561a1f900..00000000000 --- a/source/ubiqx/ubi_BinTree.h +++ /dev/null @@ -1,741 +0,0 @@ -#ifndef ubi_BinTree_H -#define ubi_BinTree_H -/* ========================================================================== ** - * ubi_BinTree.h - * - * Copyright (C) 1991-1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * ubi_BinTree manages a simple binary tree. Nothing fancy here. No height - * balancing, no restructuring. Still, a good tool for creating short, low- - * overhead sorted lists of things that need to be found in a hurry. - * - * In addition, this module provides a good basis for creating other types - * of binary tree handling modules. - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_BinTree.h,v $ - * Revision 1.1 1997/10/10 14:46:39 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.4 1997/07/26 04:11:14 crh - * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE - * and ubi_trFALSE. - * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE. - * + There used to be something called "ubi_TypeDefs.h". I got rid of it. - * + Added function ubi_btLeafNode(). - * - * Revision 2.3 1997/06/03 05:15:27 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts. - * Also changed the interface to function InitTree(). See the comments - * for this function for more information. - * - * Revision 2.2 1995/10/03 22:00:40 CRH - * Ubisized! - * - * Revision 2.1 95/03/09 23:43:46 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:00:33 CRH - * Revision 2.0 of this program includes the following changes: - * - * 1) A fix to a major typo in the RepaceNode() function. - * 2) The addition of the static function Border(). - * 3) The addition of the public functions FirstOf() and LastOf(), which - * use Border(). These functions are used with trees that allow - * duplicate keys. - * 4) A complete rewrite of the Locate() function. Locate() now accepts - * a "comparison" operator. - * 5) Overall enhancements to both code and comments. - * - * I decided to give this a new major rev number because the interface has - * changed. In particular, there are two new functions, and changes to the - * Locate() function. - * - * Revision 1.0 93/10/15 22:55:04 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH). - * - * ========================================================================== ** - */ - -/* -------------------------------------------------------------------------- ** - * Macros and constants. - * - * General purpose: - * ubi_trTRUE - Boolean TRUE. - * ubi_trFALSE - Boolean FALSE. - * - * Flags used in the tree header: - * ubi_trOVERWRITE - This flag indicates that an existing node may be - * overwritten by a new node with a matching key. - * ubi_trDUPKEY - This flag indicates that the tree allows duplicate - * keys. If the tree does allow duplicates, the - * overwrite flag is ignored. - * - * Node link array index constants: (Each node has an array of three - * pointers. One to the left, one to the right, and one back to the - * parent.) - * LEFT - Left child pointer. - * PARENT - Parent pointer. - * RIGHT - Right child pointer. - * EQUAL - Synonym for PARENT. - * - * ubi_trCompOps: These values are used in the ubi_trLocate() function. - * ubi_trLT - request the first instance of the greatest key less than - * the search key. - * ubi_trLE - request the first instance of the greatest key that is less - * than or equal to the search key. - * ubi_trEQ - request the first instance of key that is equal to the - * search key. - * ubi_trGE - request the first instance of a key that is greater than - * or equal to the search key. - * ubi_trGT - request the first instance of the first key that is greater - * than the search key. - * -------------------------------------------------------------------------- ** - */ - -#define ubi_trTRUE 0xFF -#define ubi_trFALSE 0x00 - -#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */ -#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */ - -/* Pointer array index constants... */ -#define LEFT 0x00 -#define PARENT 0x01 -#define RIGHT 0x02 -#define EQUAL PARENT - -typedef enum { - ubi_trLT = 1, - ubi_trLE, - ubi_trEQ, - ubi_trGE, - ubi_trGT - } ubi_trCompOps; - -/* -------------------------------------------------------------------------- ** - * These three macros allow simple manipulation of pointer index values (LEFT, - * RIGHT, and PARENT). - * - * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C - * uses {negative, zero, positive} values to indicate - * {less than, equal to, greater than}. - * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT, - * RIGHT} (opposite of Normalize()). Note: C comparison - * functions, such as strcmp(), return {negative, zero, - * positive} values, which are not necessarily {-1, 0, - * 1}. This macro uses the the ubi_btSgn() function to - * compensate. - * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL) - * is left as is. - * -------------------------------------------------------------------------- ** - */ -#define Normalize(W) ((char)((W)-EQUAL)) -#define AbNormal(W) ((char)( EQUAL+((char)ubi_btSgn( (W) )) )) -#define RevWay(W) ((char)((W)==LEFT?RIGHT:((W)==RIGHT?LEFT:EQUAL))) - -/* -------------------------------------------------------------------------- ** - * These macros allow us to quickly read the values of the OVERWRITE and - * DUPlicate KEY bits of the tree root flags field. - * -------------------------------------------------------------------------- ** - */ -#define Dups_OK(A) ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) -#define Ovwt_OK(A) ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE)) - -/* -------------------------------------------------------------------------- ** - * Typedefs... - * - * ubi_trBool - Your typcial true or false... - * - * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to - * indicate a key that is being searched for within the tree. - * Searching occurs whenever the ubi_trFind(), ubi_trLocate(), - * or ubi_trInsert() functions are called. - * -------------------------------------------------------------------------- ** - */ - -typedef unsigned char ubi_trBool; - -typedef void *ubi_btItemPtr; /* A pointer to data within a node. */ - -/* ------------------------------------------------------------------------- ** - * Binary Tree Node Structure: This structure defines the basic elements of - * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*! - * But, of course, I have to put the structure into this header so that - * you can use it as a building block. - * - * The fields are as follows: - * Link - an array of pointers. These pointers are manipulated by - * the BT routines. The pointers indicate the left and right - * child nodes and the parent node. By keeping track of the - * parent pointer, we avoid the need for recursive routines or - * hand-tooled stacks to keep track of our path back to the - * root. The use of these pointers is subject to change without - * notice. - * gender - a one-byte field indicating whether the node is the RIGHT or - * LEFT child of its parent. If the node is the root of the - * tree, gender will be PARENT. - * ------------------------------------------------------------------------- ** - */ -typedef struct ubi_btNodeStruct { - struct ubi_btNodeStruct *Link[ 3 ]; - char gender; - } ubi_btNode; - -typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */ - -/* ------------------------------------------------------------------------- ** - * The next three typedefs define standard function types used by the binary - * tree management routines. In particular: - * - * ubi_btCompFunc is a pointer to a comparison function. Comparison - * functions are passed an ubi_btItemPtr and an - * ubi_btNodePtr. They return a value that is (<0), 0, - * or (>0) to indicate that the Item is (respectively) - * "less than", "equal to", or "greater than" the Item - * contained within the node. (See ubi_btInitTree()). - * ubi_btActionRtn is a pointer to a function that may be called for each - * node visited when performing a tree traversal (see - * ubi_btTraverse()). The function will be passed two - * parameters: the first is a pointer to a node in the - * tree, the second is a generic pointer that may point to - * anything that you like. - * ubi_btKillNodeRtn is a pointer to a function that will deallocate the - * memory used by a node (see ubi_btKillTree()). Since - * memory management is left up to you, deallocation may - * mean anything that you want it to mean. Just remember - * that the tree *will* be destroyed and that none of the - * node pointers will be valid any more. - * ------------------------------------------------------------------------- ** - */ - -typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr ); - -typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * ); - -typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr ); - -/* -------------------------------------------------------------------------- ** - * Tree Root Structure: This structure gives us a convenient handle for - * accessing whole AVL trees. The fields are: - * root - A pointer to the root node of the AVL tree. - * count - A count of the number of nodes stored in the tree. - * cmp - A pointer to the comparison routine to be used when building or - * searching the tree. - * flags - A set of bit flags. Two flags are currently defined: - * - * ubi_trOVERWRITE - If set, this flag indicates that a new node should - * (bit 0x01) overwrite an old node if the two have identical - * keys (ie., the keys are equal). - * ubi_trDUPKEY - If set, this flag indicates that the tree is - * (bit 0x02) allowed to contain nodes with duplicate keys. - * - * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE. - * - * All of these values are set when you initialize the root structure by - * calling ubi_trInitTree(). - * -------------------------------------------------------------------------- ** - */ - -typedef struct { - ubi_btNodePtr root; /* A pointer to the root node of the tree */ - unsigned long count; /* A count of the number of nodes in the tree */ - ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */ - unsigned char flags; /* Overwrite Y|N, Duplicate keys Y|N... */ - } ubi_btRoot; - -typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */ - - -/* -------------------------------------------------------------------------- ** - * Function Prototypes. - */ - -long ubi_btSgn( long x ); - /* ------------------------------------------------------------------------ ** - * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}. - * - * Input: x - a signed long integer value. - * - * Output: the "sign" of x, represented as follows: - * -1 == negative - * 0 == zero (no sign) - * 1 == positive - * - * Note: This utility is provided in order to facilitate the conversion - * of C comparison function return values into BinTree direction - * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the - * AbNormal() conversion macro! - * - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a tree node. - * - * Input: a pointer to a ubi_btNode structure to be initialized. - * Output: a pointer to the initialized ubi_btNode structure (ie. the - * same as the input pointer). - * ------------------------------------------------------------------------ ** - */ - -ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr, - ubi_btCompFunc CompFunc, - unsigned char Flags ); - /* ------------------------------------------------------------------------ ** - * Initialize the fields of a Tree Root header structure. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure to be - * initialized. - * CompFunc - a pointer to a comparison function that will be used - * whenever nodes in the tree must be compared against - * outside values. - * Flags - One bytes worth of flags. Flags include - * ubi_trOVERWRITE and ubi_trDUPKEY. See the header - * file for more info. - * - * Output: a pointer to the initialized ubi_btRoot structure (ie. the - * same value as RootPtr). - * - * Note: The interface to this function has changed from that of - * previous versions. The <Flags> parameter replaces two - * boolean parameters that had the same basic effect. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr, - ubi_btNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ); - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ); - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_btLocate(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btNext( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Next node in the - * tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "next" node in the tree, or NULL if P pointed - * to the "last" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Previous node in - * the tree. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "previous" node in the tree, or NULL if P - * pointed to the "first" node in the tree or was NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) First node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "first" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLast( ubi_btNodePtr P ); - /* ------------------------------------------------------------------------ ** - * Given the node indicated by P, find the (sorted order) Last node in the - * subtree of which *P is the root. - * Input: P - a pointer to a node that exists in a binary tree. - * Output: A pointer to the "last" node in a subtree that has *P as its - * root. This function will return NULL only if P is NULL. - * Note: In general, you will be passing in the value of the root field - * of an ubi_btRoot structure. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ); - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the first (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the first node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr, - ubi_btItemPtr MatchMe, - ubi_btNodePtr p ); - /* ------------------------------------------------------------------------ ** - * Given a tree that a allows duplicate keys, and a pointer to a node in - * the tree, this function will return a pointer to the last (traversal - * order) node with the same key value. - * - * Input: RootPtr - A pointer to the root of the tree. - * MatchMe - A pointer to the key value. This should probably - * point to the key within node *p. - * p - A pointer to a node in the tree. - * Output: A pointer to the last node in the set of nodes with keys - * matching <FindMe>. - * Notes: Node *p MUST be in the set of nodes with keys matching - * <FindMe>. If not, this function will return NULL. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btTraverse( ubi_btRootPtr RootPtr, - ubi_btActionRtn EachNode, - void *UserData ); - /* ------------------------------------------------------------------------ ** - * Traverse a tree in sorted order (non-recursively). At each node, call - * (*EachNode)(), passing a pointer to the current node, and UserData as the - * second parameter. - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the tree to be traversed. - * EachNode - a pointer to a function to be called at each node - * as the node is visited. - * UserData - a generic pointer that may point to anything that - * you choose. - * Output: A boolean value. FALSE if the tree is empty, otherwise TRUE. - * ------------------------------------------------------------------------ ** - */ - -ubi_trBool ubi_btKillTree( ubi_btRootPtr RootPtr, - ubi_btKillNodeRtn FreeNode ); - /* ------------------------------------------------------------------------ ** - * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot - * structure. Note that this function will return FALSE if either parameter - * is NULL. - * - * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates - * the root of the tree to delete. - * FreeNode - a function that will be called for each node in the - * tree to deallocate the memory used by the node. - * - * Output: A boolean value. FALSE if either input parameter was NULL, else - * TRUE. - * - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader ); - /* ------------------------------------------------------------------------ ** - * Returns a pointer to a leaf node. - * - * Input: leader - Pointer to a node at which to start the descent. - * - * Output: A pointer to a leaf node selected in a somewhat arbitrary - * manner. - * - * Notes: I wrote this function because I was using splay trees as a - * database cache. The cache had a maximum size on it, and I - * needed a way of choosing a node to sacrifice if the cache - * became full. In a splay tree, less recently accessed nodes - * tend toward the bottom of the tree, meaning that leaf nodes - * are good candidates for removal. (I really can't think of - * any other reason to use this function.) - * + In a simple binary tree or an AVL tree, the most recently - * added nodes tend to be nearer the bottom, making this a *bad* - * way to choose which node to remove from the cache. - * + Randomizing the traversal order is probably a good idea. You - * can improve the randomization of leaf node selection by passing - * in pointers to nodes other than the root node each time. A - * pointer to any node in the tree will do. Of course, if you - * pass a pointer to a leaf node you'll get the same thing back. - * - * ------------------------------------------------------------------------ ** - */ - - -int ubi_btModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by - * including the appropriate module header. - */ - -#define ubi_trItemPtr ubi_btItemPtr - -#define ubi_trNode ubi_btNode -#define ubi_trNodePtr ubi_btNodePtr - -#define ubi_trRoot ubi_btRoot -#define ubi_trRootPtr ubi_btRootPtr - -#define ubi_trCompFunc ubi_btCompFunc -#define ubi_trActionRtn ubi_btActionRtn -#define ubi_trKillNodeRtn ubi_btKillNodeRtn - -#define ubi_trSgn( x ) ubi_btSgn( x ) - -#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) ) - -#define ubi_trInitTree( Rp, Cf, Fl ) \ - ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) ) - -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) - -#define ubi_trRemove( Rp, Dn ) \ - ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) - -#define ubi_trLocate( Rp, Ip, Op ) \ - ubi_btLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#define ubi_trFind( Rp, Ip ) \ - ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) ) - -#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) ) - -#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) ) - -#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) ) - -#define ubi_trFirstOf( Rp, Ip, P ) \ - ubi_btFirstOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#define ubi_trLastOf( Rp, Ip, P ) \ - ubi_btLastOf( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_btNodePtr)(P) ) - -#define ubi_trTraverse( Rp, En, Ud ) \ - ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud)) - -#define ubi_trKillTree( Rp, Fn ) \ - ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) ) - -#define ubi_trLeafNode( Nd ) \ - ubi_btLeafNode( (ubi_btNodePtr)(Nd) ) - -#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l ) - -/* ========================================================================== */ -#endif /* ubi_BinTree_H */ diff --git a/source/ubiqx/ubi_SplayTree.c b/source/ubiqx/ubi_SplayTree.c deleted file mode 100644 index e6b30dd8fcc..00000000000 --- a/source/ubiqx/ubi_SplayTree.c +++ /dev/null @@ -1,468 +0,0 @@ -/* ========================================================================== ** - * ubi_SplayTree.c - * - * Copyright (C) 1993-1995 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module implements "splay" trees. Splay trees are binary trees - * that are rearranged (splayed) whenever a node is accessed. The - * splaying process *tends* to make the tree bushier (improves balance), - * and the nodes that are accessed most frequently *tend* to be closer to - * the top. - * - * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and - * Robert Tarjan. Journal of the Association for Computing - * Machinery Vol 32, No. 3, July 1985 pp. 652-686 - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_SplayTree.c,v $ - * Revision 1.1 1997/10/10 14:46:40 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.5 1997/07/26 04:15:42 crh - * + Cleaned up a few minor syntax annoyances that gcc discovered for me. - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * - * Revision 2.4 1997/06/03 04:42:21 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.3 1995/10/03 22:19:07 CRH - * Ubisized! - * Also, added the function ubi_sptSplay(). - * - * Revision 2.1 95/03/09 23:54:42 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:34:46 CRH - * This module was updated to match the interface changes made to the - * ubi_BinTree module. In particular, the interface to the Locate() function - * has changed. See ubi_BinTree for more information on changes and new - * functions. - * - * The revision number was also upped to match ubi_BinTree. - * - * Revision 1.1 93/10/18 20:35:16 CRH - * I removed the hard-coded logical device names from the include file - * specifications. CRH - * - * Revision 1.0 93/10/15 23:00:15 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * Revision 0.1 93/04/25 22:03:32 CRH - * Simply changed the <exec/types.h> #include reference the .c file to - * use <stdlib.h> instead. The latter is portable, the former is not. - * - * Revision 0.0 93/04/21 23:05:52 CRH - * Initial version, written by Christopher R. Hertel. - * This module implements Splay Trees using the ubi_BinTree module as a basis. - * - * ========================================================================== ** - */ - -#include <stdlib.h> /* Defines NULL for us. */ -#include "ubi_SplayTree.h" /* Header for THIS module. */ - -/* ========================================================================== ** - * Static data. - */ - -static char ModuleID[] = "ubi_SplayTree\n\ -\t$Revision: 1.1 $\n\ -\t$Date: 1997/10/10 14:46:40 $\n\ -\t$Author: crh $\n"; - - -/* ========================================================================== ** - * Private functions... - */ - -static void Rotate( ubi_btNodePtr p ) - /* ------------------------------------------------------------------------ ** - * This function performs a single rotation, moving node *p up one level - * in the tree. - * - * Input: p - a pointer to an ubi_btNode in a tree. - * - * Output: None. - * - * Notes: This implements a single rotation in either direction (left - * or right). This is the basic building block of all splay - * tree rotations. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr parentp; - ubi_btNodePtr tmp; - char way; - char revway; - - parentp = p->Link[PARENT]; /* Find parent. */ - - if( parentp ) /* If no parent, then we're already the root. */ - { - way = p->gender; - revway = RevWay(way); - tmp = p->Link[revway]; - - parentp->Link[way] = tmp; - if( tmp ) - { - tmp->Link[PARENT] = parentp; - tmp->gender = way; - } - - tmp = parentp->Link[PARENT]; - p->Link[PARENT] = tmp; - p->gender = parentp->gender; - if( tmp ) - tmp->Link[p->gender] = p; - - parentp->Link[PARENT] = p; - parentp->gender = revway; - p->Link[revway] = parentp; - } - } /* Rotate */ - -static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe ) - /* ------------------------------------------------------------------------ ** - * Move the node indicated by SplayWithMe to the root of the tree by - * splaying the tree. - * - * Input: SplayWithMe - A pointer to an ubi_btNode within a tree. - * - * Output: A pointer to the root of the splay tree (i.e., the same as - * SplayWithMe). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr parent; - - while( (parent = SplayWithMe->Link[PARENT]) ) - { - if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */ - Rotate( parent ); - else - { - if( EQUAL != parent->gender ) /* Zig-Zag */ - Rotate( SplayWithMe ); - } - Rotate( SplayWithMe ); /* Zig */ - } /* while */ - return( SplayWithMe ); - } /* Splay */ - -/* ========================================================================== ** - * Exported utilities. - */ - -ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ) - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * splay tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr OtherP; - - if( !(OldNode) ) - OldNode = &OtherP; - - if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) ) - { - RootPtr->root = Splay( NewNode ); - return( ubi_trTRUE ); - } - - /* Splay the unreplacable, duplicate keyed, unique, old node. */ - RootPtr->root = Splay( (*OldNode) ); - return( ubi_trFALSE ); - } /* ubi_sptInsert */ - -ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ) - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - (void)Splay( DeadNode ); /* Move dead node to root. */ - if( (p = DeadNode->Link[LEFT]) ) /* If left subtree exists... */ - { - ubi_btNodePtr q = DeadNode->Link[RIGHT]; - - p->Link[PARENT] = NULL; /* Left subtree node becomes root.*/ - p->gender = PARENT; - p = ubi_btLast( p ); /* Find rightmost left tree node..*/ - p->Link[RIGHT] = q; /* ...attach right tree. */ - if( q ) - q->Link[PARENT] = p; - RootPtr->root = Splay( p ); /* Resplay at p. */ - } - else - { - if( (p = DeadNode->Link[RIGHT]) ) /* No left, but right subtree... */ - { /* ...exists... */ - p->Link[PARENT] = NULL; /* Right subtree root becomes... */ - p->gender = PARENT; /* ...overall tree root. */ - RootPtr->root = p; - } - else - RootPtr->root = NULL; /* No subtrees => empty tree. */ - } - - (RootPtr->count)--; /* Decrement node count. */ - return( DeadNode ); /* Return pointer to pruned node. */ - } /* ubi_sptRemove */ - -ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ) - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - p = ubi_btLocate( RootPtr, FindMe, CompOp ); - if( p ) - RootPtr->root = Splay( p ); - return( p ); - } /* ubi_sptLocate */ - -ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ) - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_sptLocate(). - * ------------------------------------------------------------------------ ** - */ - { - ubi_btNodePtr p; - - p = ubi_btFind( RootPtr, FindMe ); - if( p ) - RootPtr->root = Splay( p ); - return( p ); - } /* ubi_sptFind */ - -void ubi_sptSplay( ubi_btRootPtr RootPtr, - ubi_btNodePtr SplayMe ) - /* ------------------------------------------------------------------------ ** - * This function allows you to splay the tree at a given node, thus moving - * the node to the top of the tree. - * - * Input: - * RootPtr - a pointer to the header of the tree to be splayed. - * SplayMe - a pointer to a node within the tree. This will become - * the new root node. - * Output: None. - * - * Notes: This is an uncharacteristic function for this group of modules - * in that it provides access to the internal balancing routines, - * which would normally be hidden. - * Splaying the tree will not damage it (assuming that I've done - * *my* job), but there is overhead involved. I don't recommend - * that you use this function unless you understand the underlying - * Splay Tree principles involved. - * ------------------------------------------------------------------------ ** - */ - { - RootPtr->root = Splay( SplayMe ); - } /* ubi_sptSplay */ - -int ubi_sptModuleID( int size, char *list[] ) - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - { - if( size > 0 ) - { - list[0] = ModuleID; - if( size > 1 ) - return( 1 + ubi_btModuleID( --size, &(list[1]) ) ); - return( 1 ); - } - return( 0 ); - } /* ubi_sptModuleID */ - -/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_SplayTree.h b/source/ubiqx/ubi_SplayTree.h deleted file mode 100644 index d20933ed4ce..00000000000 --- a/source/ubiqx/ubi_SplayTree.h +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef ubi_SplayTree_H -#define ubi_SplayTree_H -/* ========================================================================== ** - * ubi_SplayTree.h - * - * Copyright (C) 1993,1995 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * - * This module implements "splay" trees. Splay trees are binary trees - * that are rearranged (splayed) whenever a node is accessed. The - * splaying process *tends* to make the tree bushier (improves balance), - * and the nodes that are accessed most frequently *tend* to be closer to - * the top. - * - * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and - * Robert Tarjan. Journal of the Association for Computing - * Machinery Vol 32, No. 3, July 1985 pp. 652-686 - * - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_SplayTree.h,v $ - * Revision 1.1 1997/10/10 14:46:42 crh - * This is the ubiqx binary tree and linked list library. - * This library is being included as part of the Samba distribution. - * (Hurray!) - * - * Revision 2.5 1997/07/26 04:15:46 crh - * + Cleaned up a few minor syntax annoyances that gcc discovered for me. - * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE. - * - * Revision 2.4 1997/06/03 05:22:56 crh - * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing - * problems. - * - * Revision 2.3 1995/10/03 22:19:37 CRH - * Ubisized! - * Also, added the function ubi_sptSplay(). - * - * Revision 2.1 95/03/09 23:55:04 CRH - * Added the ModuleID static string and function. These modules are now - * self-identifying. - * - * Revision 2.0 95/02/27 22:34:55 CRH - * This module was updated to match the interface changes made to the - * ubi_BinTree module. In particular, the interface to the Locate() function - * has changed. See ubi_BinTree for more information on changes and new - * functions. - * - * The revision number was also upped to match ubi_BinTree. - * - * - * Revision 1.0 93/10/15 22:59:36 CRH - * With this revision, I have added a set of #define's that provide a single, - * standard API to all existing tree modules. Until now, each of the three - * existing modules had a different function and typedef prefix, as follows: - * - * Module Prefix - * ubi_BinTree ubi_bt - * ubi_AVLtree ubi_avl - * ubi_SplayTree ubi_spt - * - * To further complicate matters, only those portions of the base module - * (ubi_BinTree) that were superceeded in the new module had the new names. - * For example, if you were using ubi_AVLtree, the AVL node structure was - * named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using - * SplayTree, the locate function was called "ubi_sptLocate", but the next - * and previous functions remained "ubi_btNext" and "ubi_btPrev". - * - * This was not too terrible if you were familiar with the modules and knew - * exactly which tree model you wanted to use. If you wanted to be able to - * change modules (for speed comparisons, etc), things could get messy very - * quickly. - * - * So, I have added a set of defined names that get redefined in any of the - * descendant modules. To use this standardized interface in your code, - * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with - * "ubi_tr". The "ubi_tr" names will resolve to the correct function or - * datatype names for the module that you are using. Just remember to - * include the header for that module in your program file. Because these - * names are handled by the preprocessor, there is no added run-time - * overhead. - * - * Note that the original names do still exist, and can be used if you wish - * to write code directly to a specific module. This should probably only be - * done if you are planning to implement a new descendant type, such as - * red/black trees. CRH - * - * Revision 0.0 93/04/21 23:07:13 CRH - * Initial version, written by Christopher R. Hertel. - * This module implements Splay Trees using the ubi_BinTree module as a basis. - * - * ========================================================================== ** - */ - -#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */ - -/* ========================================================================== ** - * Function prototypes... - */ - -ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr, - ubi_btNodePtr NewNode, - ubi_btItemPtr ItemPtr, - ubi_btNodePtr *OldNode ); - /* ------------------------------------------------------------------------ ** - * This function uses a non-recursive algorithm to add a new element to the - * splay tree. - * - * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates - * the root of the tree to which NewNode is to be added. - * NewNode - a pointer to an ubi_btNode structure that is NOT - * part of any tree. - * ItemPtr - A pointer to the sort key that is stored within - * *NewNode. ItemPtr MUST point to information stored - * in *NewNode or an EXACT DUPLICATE. The key data - * indicated by ItemPtr is used to place the new node - * into the tree. - * OldNode - a pointer to an ubi_btNodePtr. When searching - * the tree, a duplicate node may be found. If - * duplicates are allowed, then the new node will - * be simply placed into the tree. If duplicates - * are not allowed, however, then one of two things - * may happen. - * 1) if overwritting *is not* allowed, this - * function will return FALSE (indicating that - * the new node could not be inserted), and - * *OldNode will point to the duplicate that is - * still in the tree. - * 2) if overwritting *is* allowed, then this - * function will swap **OldNode for *NewNode. - * In this case, *OldNode will point to the node - * that was removed (thus allowing you to free - * the node). - * ** If you are using overwrite mode, ALWAYS ** - * ** check the return value of this parameter! ** - * Note: You may pass NULL in this parameter, the - * function knows how to cope. If you do this, - * however, there will be no way to return a - * pointer to an old (ie. replaced) node (which is - * a problem if you are using overwrite mode). - * - * Output: a boolean value indicating success or failure. The function - * will return FALSE if the node could not be added to the tree. - * Such failure will only occur if duplicates are not allowed, - * nodes cannot be overwritten, AND a duplicate key was found - * within the tree. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode ); - /* ------------------------------------------------------------------------ ** - * This function removes the indicated node from the tree. - * - * Input: RootPtr - A pointer to the header of the tree that contains - * the node to be removed. - * DeadNode - A pointer to the node that will be removed. - * - * Output: This function returns a pointer to the node that was removed - * from the tree (ie. the same as DeadNode). - * - * Note: The node MUST be in the tree indicated by RootPtr. If not, - * strange and evil things will happen to your trees. - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe, - ubi_trCompOps CompOp ); - /* ------------------------------------------------------------------------ ** - * The purpose of ubi_btLocate() is to find a node or set of nodes given - * a target value and a "comparison operator". The Locate() function is - * more flexible and (in the case of trees that may contain dupicate keys) - * more precise than the ubi_btFind() function. The latter is faster, - * but it only searches for exact matches and, if the tree contains - * duplicates, Find() may return a pointer to any one of the duplicate- - * keyed records. - * - * Input: - * RootPtr - A pointer to the header of the tree to be searched. - * FindMe - An ubi_btItemPtr that indicates the key for which to - * search. - * CompOp - One of the following: - * CompOp Return a pointer to the node with - * ------ --------------------------------- - * ubi_trLT - the last key value that is less - * than FindMe. - * ubi_trLE - the first key matching FindMe, or - * the last key that is less than - * FindMe. - * ubi_trEQ - the first key matching FindMe. - * ubi_trGE - the first key matching FindMe, or the - * first key greater than FindMe. - * ubi_trGT - the first key greater than FindMe. - * Output: - * A pointer to the node matching the criteria listed above under - * CompOp, or NULL if no node matched the criteria. - * - * Notes: - * In the case of trees with duplicate keys, Locate() will behave as - * follows: - * - * Find: 3 Find: 3 - * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 - * ^ ^ ^ ^ ^ - * LT EQ GT LE GE - * - * That is, when returning a pointer to a node with a key that is LESS - * THAN the target key (FindMe), Locate() will return a pointer to the - * LAST matching node. - * When returning a pointer to a node with a key that is GREATER - * THAN the target key (FindMe), Locate() will return a pointer to the - * FIRST matching node. - * - * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). - * ------------------------------------------------------------------------ ** - */ - -ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr, - ubi_btItemPtr FindMe ); - /* ------------------------------------------------------------------------ ** - * This function performs a non-recursive search of a tree for any node - * matching a specific key. - * - * Input: - * RootPtr - a pointer to the header of the tree to be searched. - * FindMe - a pointer to the key value for which to search. - * - * Output: - * A pointer to a node with a key that matches the key indicated by - * FindMe, or NULL if no such node was found. - * - * Note: In a tree that allows duplicates, the pointer returned *might - * not* point to the (sequentially) first occurance of the - * desired key. In such a tree, it may be more useful to use - * ubi_sptLocate(). - * ------------------------------------------------------------------------ ** - */ - -void ubi_sptSplay( ubi_btRootPtr RootPtr, - ubi_btNodePtr SplayMe ); - /* ------------------------------------------------------------------------ ** - * This function allows you to splay the tree at a given node, thus moving - * the node to the top of the tree. - * - * Input: - * RootPtr - a pointer to the header of the tree to be splayed. - * SplayMe - a pointer to a node within the tree. This will become - * the new root node. - * Output: None. - * - * Notes: This is an uncharacteristic function for this group of modules - * in that it provides access to the internal balancing routines, - * which would normally be hidden. - * Splaying the tree will not damage it (assuming that I've done - * *my* job), but there is overhead involved. I don't recommend - * that you use this function unless you understand the underlying - * Splay Tree principles involved. - * ------------------------------------------------------------------------ ** - */ - -int ubi_sptModuleID( int size, char *list[] ); - /* ------------------------------------------------------------------------ ** - * Returns a set of strings that identify the module. - * - * Input: size - The number of elements in the array <list>. - * list - An array of pointers of type (char *). This array - * should, initially, be empty. This function will fill - * in the array with pointers to strings. - * Output: The number of elements of <list> that were used. If this value - * is less than <size>, the values of the remaining elements are - * not guaranteed. - * - * Notes: Please keep in mind that the pointers returned indicate strings - * stored in static memory. Don't free() them, don't write over - * them, etc. Just read them. - * ------------------------------------------------------------------------ ** - */ - -/* -------------------------------------------------------------------------- ** - * Masquarade... - * - * This set of defines allows you to write programs that will use any of the - * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree). - * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by - * including the appropriate module header. - */ - -#undef ubi_trInsert -#undef ubi_trRemove -#undef ubi_trLocate -#undef ubi_trFind -#undef ubi_trModuleID - -#define ubi_trInsert( Rp, Nn, Ip, On ) \ - ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \ - (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) ) - -#define ubi_trRemove( Rp, Dn ) \ - ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) ) - -#define ubi_trLocate( Rp, Ip, Op ) \ - ubi_sptLocate( (ubi_btRootPtr)(Rp), \ - (ubi_btItemPtr)(Ip), \ - (ubi_trCompOps)(Op) ) - -#define ubi_trFind( Rp, Ip ) \ - ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) ) - -#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l ) - -/* ================================ The End ================================= */ -#endif /* ubi_SplayTree_H */ - - - - - diff --git a/source/ubiqx/ubi_dLinkList.c b/source/ubiqx/ubi_dLinkList.c deleted file mode 100644 index 2eb721e1eed..00000000000 --- a/source/ubiqx/ubi_dLinkList.c +++ /dev/null @@ -1,151 +0,0 @@ -/* ========================================================================== ** - * ubi_dLinkList.c - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements simple doubly-linked lists. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_dLinkList.c,v $ - * Revision 1.2 1997/10/15 03:11:46 crh - * These are the ubiqx modules, as included with the Samba distribution. - * Updated the linked list module, which has new and changed macros. - * - * Revision 0.3 1997/10/15 03:05:39 crh - * Added some handy type casting to the macros. Added AddHere and RemThis - * macros. - * - * Revision 0.2 1997/10/08 03:07:21 crh - * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() - * macro, which was passing the wrong value for <After> to Insert(). - * - * Revision 0.1 1997/10/07 04:34:07 crh - * Initial Revision. - * - * - * ========================================================================== ** - */ - -#include "ubi_dLinkList.h" - -/* ========================================================================== ** - * Functions... - */ - -ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a doubly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - { - ListPtr->Head = NULL; - ListPtr->Tail = NULL; - ListPtr->count = 0; - return( ListPtr ); - } /* ubi_dlInitList */ - -ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, - ubi_dlNodePtr New, - ubi_dlNodePtr After ) - /* ------------------------------------------------------------------------ ** - * Insert a new node into the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the new node. - * After - NULL, or a pointer to a node that is already in the - * list. - * If NULL, then <New> will be added at the head of the - * list, else it will be added following <After>. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - { - if( NULL == After ) - { - New->Next = ListPtr->Head; - New->Prev = NULL; - if( NULL != ListPtr->Head ) - ListPtr->Head->Prev = New; - else - ListPtr->Tail = New; - ListPtr->Head = New; - } - else - { - New->Next = After->Next; - New->Prev = After; - if( NULL != After->Next ) - After->Next->Prev = New; - else - ListPtr->Tail = New; - After->Next = New; - } - - ++(ListPtr->count); - - return( New ); - } /* ubi_dlInsert */ - -ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) - /* ------------------------------------------------------------------------ ** - * Remove a node from the list. - * - * Input: ListPtr - A pointer to the list from which <Old> is to be - * removed. - * Old - A pointer to the node that is to be removed from the - * list. - * - * Output: A pointer to the node that was removed (i.e., <Old>). - * - * ------------------------------------------------------------------------ ** - */ - { - if( NULL != Old ) - { - if( Old->Next ) - Old->Next->Prev = Old->Prev; - else - ListPtr->Tail = Old->Prev; - - if( Old->Prev ) - Old->Prev->Next = Old->Next; - else - ListPtr->Head = Old->Next; - - --(ListPtr->count); - } - - return( Old ); - } /* ubi_dlRemove */ - - -/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_dLinkList.h b/source/ubiqx/ubi_dLinkList.h deleted file mode 100644 index 802513aaf9b..00000000000 --- a/source/ubiqx/ubi_dLinkList.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef ubi_dLinkList_H -#define ubi_dLinkList_H -/* ========================================================================== ** - * ubi_dLinkList.h - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements simple doubly-linked lists. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_dLinkList.h,v $ - * Revision 1.2 1997/10/15 03:11:46 crh - * These are the ubiqx modules, as included with the Samba distribution. - * Updated the linked list module, which has new and changed macros. - * - * Revision 0.3 1997/10/15 03:04:31 crh - * Added some handy type casting to the macros. Added AddHere and RemThis - * macros. - * - * Revision 0.2 1997/10/08 03:08:16 crh - * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() - * macro, which was passing the wrong value for <After> to Insert(). - * - * Revision 0.1 1997/10/07 04:34:38 crh - * Initial Revision. - * - * - * ========================================================================== ** - */ - -#include <stdlib.h> - - -/* ========================================================================== ** - * Typedefs... - * - * ubi_dlNode - This is the basic node structure. - * ubi_dlNodePtr - Pointer to a node. - * ubi_dlList - This is the list header structure. - * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). - * - */ - -typedef struct ubi_dlListNode - { - struct ubi_dlListNode *Next; - struct ubi_dlListNode *Prev; - } ubi_dlNode; - -typedef ubi_dlNode *ubi_dlNodePtr; - -typedef struct - { - ubi_dlNodePtr Head; - ubi_dlNodePtr Tail; - unsigned long count; - } ubi_dlList; - -typedef ubi_dlList *ubi_dlListPtr; - -/* ========================================================================== ** - * Macros... - * - * ubi_dlAddHead - Add a new node at the head of the list. - * ubi_dlAddTail - Add a new node at the tail of the list. - * ubi_dlAddHere - Add a node following the given node. - * ubi_dlRemHead - Remove the node at the head of the list, if any. - * ubi_dlRemTail - Remove the node at the tail of the list, if any. - * ubi_dlRemThis - Remove the indicated node. - * ubi_dlFirst - Return a pointer to the first node in the list, if any. - * ubi_dlLast - Return a pointer to the last node in the list, if any. - * ubi_dlNext - Given a node, return a pointer to the next node. - * ubi_dlPrev - Given a node, return a pointer to the previous node. - * - * Note that all of these provide type casting of the parameters. The - * Add and Rem macros are nothing more than nice front-ends to the - * Insert and Remove operations. - * - */ - -#define ubi_dlAddHead( L, N ) \ - ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL ) - -#define ubi_dlAddTail( L, N ) \ - ubi_dlInsert( (ubi_dlListPtr)(L), \ - (ubi_dlNodePtr)(N), \ - (((ubi_dlListPtr)(L))->Tail) ) - -#define ubi_dlAddHere( L, N, P ) \ - ubi_dlInsert( (ubi_dlListPtr)(L), \ - (ubi_dlNodePtr)(N), \ - (ubi_dlNodePtr)(P) ) - -#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ - (((ubi_dlListPtr)(L))->Head) ) - -#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ - (((ubi_dlListPtr)(L))->Tail) ) - -#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \ - (ubi_dlNodePtr)(N) ) - -#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head) - -#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail) - -#define ubi_dlNext( N ) (((ubi_dlNodePtr)(N))->Next) - -#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev) - - -/* ========================================================================== ** - * Function prototypes... - */ - -ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a doubly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, - ubi_dlNodePtr New, - ubi_dlNodePtr After ); - /* ------------------------------------------------------------------------ ** - * Insert a new node into the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the new node. - * After - NULL, or a pointer to a node that is already in the - * list. - * If NULL, then <New> will be added at the head of the - * list, else it will be added following <After>. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); - /* ------------------------------------------------------------------------ ** - * Remove a node from the list. - * - * Input: ListPtr - A pointer to the list from which <Old> is to be - * removed. - * Old - A pointer to the node that is to be removed from the - * list. - * - * Output: A pointer to the node that was removed (i.e., <Old>). - * - * ------------------------------------------------------------------------ ** - */ - - -/* ================================ The End ================================= */ -#endif /* ubi_dLinkList_H */ diff --git a/source/ubiqx/ubi_sLinkList.c b/source/ubiqx/ubi_sLinkList.c deleted file mode 100644 index 03694f4f9c7..00000000000 --- a/source/ubiqx/ubi_sLinkList.c +++ /dev/null @@ -1,102 +0,0 @@ -/* ========================================================================== ** - * ubi_sLinkList.c - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements a really simple singly-linked list. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_sLinkList.c,v $ - * Revision 1.1 1997/10/15 17:59:58 crh - * Added ubi_sLinkList module which manages simple singly-linked lists. - * - * ========================================================================== ** - */ - -#include "ubi_sLinkList.h" - -/* ========================================================================== ** - * Functions... - */ - -ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ) - /* ------------------------------------------------------------------------ ** - * Initialize a singly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - { - ListPtr->Head = NULL; - ListPtr->count = 0; - return( ListPtr ); - } /* ubi_slInitList */ - -ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, - ubi_slNodePtr New ) - /* ------------------------------------------------------------------------ ** - * Insert a new node at the head of the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the node that is to be added to the list. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - { - New->Next = ListPtr->Head; - ListPtr->Head = New; - ++(ListPtr->count); - return( New ); - } /* ubi_slInsert */ - -ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr ) - /* ------------------------------------------------------------------------ ** - * Remove a node from the head of the list. - * - * Input: ListPtr - A pointer to the list from which the node is to be - * removed. - * - * Output: A pointer to the node that was removed. - * - * ------------------------------------------------------------------------ ** - */ - { - ubi_slNodePtr Old = ListPtr->Head; - - if( NULL != Old ) - { - ListPtr->Head = Old->Next; - --(ListPtr->count); - } - return( Old ); - } /* ubi_slRemove */ - - -/* ================================ The End ================================= */ diff --git a/source/ubiqx/ubi_sLinkList.h b/source/ubiqx/ubi_sLinkList.h deleted file mode 100644 index 80050e41271..00000000000 --- a/source/ubiqx/ubi_sLinkList.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef ubi_sLinkList_H -#define ubi_sLinkList_H -/* ========================================================================== ** - * ubi_sLinkList.h - * - * Copyright (C) 1997 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * -------------------------------------------------------------------------- ** - * This module implements a really simple singly-linked list. - * -------------------------------------------------------------------------- ** - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** - * - * $Log: ubi_sLinkList.h,v $ - * Revision 1.1 1997/10/15 17:59:58 crh - * Added ubi_sLinkList module which manages simple singly-linked lists. - * - * ========================================================================== ** - */ - -#include <stdlib.h> - - -/* ========================================================================== ** - * Typedefs... - * - * ubi_slNode - This is the basic node structure. - * ubi_slNodePtr - Pointer to a node. - * ubi_slList - This is the list header structure. - * ubi_slListPtr - Pointer to a List (i.e., a list header structure). - * - */ - -typedef struct ubi_slListNode - { - struct ubi_slListNode *Next; - } ubi_slNode; - -typedef ubi_slNode *ubi_slNodePtr; - -typedef struct - { - ubi_slNodePtr Head; - unsigned long count; - } ubi_slList; - -typedef ubi_slList *ubi_slListPtr; - -/* ========================================================================== ** - * Macros... - * - * ubi_slAddHead - Add a new node at the head of the list. - * ubi_slRemHead - Remove the node at the head of the list, if any. - * ubi_slFirst - Return a pointer to the first node in the list, if any. - * ubi_slNext - Given a node, return a pointer to the next node. - * - * Note that all of these provide type casting of the parameters. The - * Add and Rem macros are nothing more than nice front-ends to the - * Insert and Remove operations. - * - */ - -#define ubi_slAddHead( L, N ) \ - ubi_slInsert( (ubi_slListPtr)(L), (ubi_slNodePtr)(N) ) - -#define ubi_slRemHead( L ) ubi_slRemove( (ubi_slListPtr)(L) ) - -#define ubi_slFirst( L ) (((ubi_slListPtr)(L))->Head) - -#define ubi_slNext( N ) (((ubi_slNodePtr)(N))->Next) - - -/* ========================================================================== ** - * Function prototypes... - */ - -ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr ); - /* ------------------------------------------------------------------------ ** - * Initialize a singly-linked list header. - * - * Input: ListPtr - A pointer to the list structure that is to be - * initialized for use. - * - * Output: A pointer to the initialized list header (i.e., same as - * <ListPtr>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr, - ubi_slNodePtr New ); - /* ------------------------------------------------------------------------ ** - * Insert a new node at the head of the list. - * - * Input: ListPtr - A pointer to the list into which the node is to - * be inserted. - * New - Pointer to the node that is to be added to the list. - * - * Output: A pointer to the node that was inserted into the list (i.e., - * the same as <New>). - * - * ------------------------------------------------------------------------ ** - */ - -ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr ); - /* ------------------------------------------------------------------------ ** - * Remove a node from the head of the list. - * - * Input: ListPtr - A pointer to the list from which the node is to be - * removed. - * - * Output: A pointer to the node that was removed. - * - * ------------------------------------------------------------------------ ** - */ - -/* ================================ The End ================================= */ -#endif /* ubi_sLinkList_H */ -- cgit From a88ae60fc33e3598f46dfc38e930e261d5e06888 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 16 Oct 1997 00:55:11 +0000 Subject: This code manages a simple doubly-linked list. --- source/ubi_dLinkList.c | 146 ++++++++++++++++++++++++++++++++++++++++ source/ubi_dLinkList.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 source/ubi_dLinkList.c create mode 100644 source/ubi_dLinkList.h diff --git a/source/ubi_dLinkList.c b/source/ubi_dLinkList.c new file mode 100644 index 00000000000..49bf495b9dc --- /dev/null +++ b/source/ubi_dLinkList.c @@ -0,0 +1,146 @@ +/* ========================================================================== ** + * ubi_dLinkList.c + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Revision 0.3 1997/10/15 03:05:39 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:07:21 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:07 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include "ubi_dLinkList.h" + +/* ========================================================================== ** + * Functions... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ) + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + { + ListPtr->Head = NULL; + ListPtr->Tail = NULL; + ListPtr->count = 0; + return( ListPtr ); + } /* ubi_dlInitList */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ) + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL == After ) + { + New->Next = ListPtr->Head; + New->Prev = NULL; + if( NULL != ListPtr->Head ) + ListPtr->Head->Prev = New; + else + ListPtr->Tail = New; + ListPtr->Head = New; + } + else + { + New->Next = After->Next; + New->Prev = After; + if( NULL != After->Next ) + After->Next->Prev = New; + else + ListPtr->Tail = New; + After->Next = New; + } + + ++(ListPtr->count); + + return( New ); + } /* ubi_dlInsert */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ) + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + { + if( NULL != Old ) + { + if( Old->Next ) + Old->Next->Prev = Old->Prev; + else + ListPtr->Tail = Old->Prev; + + if( Old->Prev ) + Old->Prev->Next = Old->Next; + else + ListPtr->Head = Old->Next; + + --(ListPtr->count); + } + + return( Old ); + } /* ubi_dlRemove */ + + +/* ================================ The End ================================= */ diff --git a/source/ubi_dLinkList.h b/source/ubi_dLinkList.h new file mode 100644 index 00000000000..1facf92d3b1 --- /dev/null +++ b/source/ubi_dLinkList.h @@ -0,0 +1,178 @@ +#ifndef ubi_dLinkList_H +#define ubi_dLinkList_H +/* ========================================================================== ** + * ubi_dLinkList.h + * + * Copyright (C) 1997 by Christopher R. Hertel + * + * Email: crh@ubiqx.mn.org + * -------------------------------------------------------------------------- ** + * This module implements simple doubly-linked lists. + * -------------------------------------------------------------------------- ** + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- ** + * + * Revision 0.3 1997/10/15 03:04:31 crh + * Added some handy type casting to the macros. Added AddHere and RemThis + * macros. + * + * Revision 0.2 1997/10/08 03:08:16 crh + * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead() + * macro, which was passing the wrong value for <After> to Insert(). + * + * Revision 0.1 1997/10/07 04:34:38 crh + * Initial Revision. + * + * + * ========================================================================== ** + */ + +#include <stdlib.h> + + +/* ========================================================================== ** + * Typedefs... + * + * ubi_dlNode - This is the basic node structure. + * ubi_dlNodePtr - Pointer to a node. + * ubi_dlList - This is the list header structure. + * ubi_dlListPtr - Pointer to a List (i.e., a list header structure). + * + */ + +typedef struct ubi_dlListNode + { + struct ubi_dlListNode *Next; + struct ubi_dlListNode *Prev; + } ubi_dlNode; + +typedef ubi_dlNode *ubi_dlNodePtr; + +typedef struct + { + ubi_dlNodePtr Head; + ubi_dlNodePtr Tail; + unsigned long count; + } ubi_dlList; + +typedef ubi_dlList *ubi_dlListPtr; + +/* ========================================================================== ** + * Macros... + * + * ubi_dlAddHead - Add a new node at the head of the list. + * ubi_dlAddTail - Add a new node at the tail of the list. + * ubi_dlAddHere - Add a node following the given node. + * ubi_dlRemHead - Remove the node at the head of the list, if any. + * ubi_dlRemTail - Remove the node at the tail of the list, if any. + * ubi_dlRemThis - Remove the indicated node. + * ubi_dlFirst - Return a pointer to the first node in the list, if any. + * ubi_dlLast - Return a pointer to the last node in the list, if any. + * ubi_dlNext - Given a node, return a pointer to the next node. + * ubi_dlPrev - Given a node, return a pointer to the previous node. + * + * Note that all of these provide type casting of the parameters. The + * Add and Rem macros are nothing more than nice front-ends to the + * Insert and Remove operations. + * + */ + +#define ubi_dlAddHead( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL ) + +#define ubi_dlAddTail( L, N ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (((ubi_dlListPtr)(L))->Tail) ) + +#define ubi_dlAddHere( L, N, P ) \ + ubi_dlInsert( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N), \ + (ubi_dlNodePtr)(P) ) + +#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Head) ) + +#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (((ubi_dlListPtr)(L))->Tail) ) + +#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \ + (ubi_dlNodePtr)(N) ) + +#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head) + +#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail) + +#define ubi_dlNext( N ) (((ubi_dlNodePtr)(N))->Next) + +#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev) + + +/* ========================================================================== ** + * Function prototypes... + */ + +ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr ); + /* ------------------------------------------------------------------------ ** + * Initialize a doubly-linked list header. + * + * Input: ListPtr - A pointer to the list structure that is to be + * initialized for use. + * + * Output: A pointer to the initialized list header (i.e., same as + * <ListPtr>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr, + ubi_dlNodePtr New, + ubi_dlNodePtr After ); + /* ------------------------------------------------------------------------ ** + * Insert a new node into the list. + * + * Input: ListPtr - A pointer to the list into which the node is to + * be inserted. + * New - Pointer to the new node. + * After - NULL, or a pointer to a node that is already in the + * list. + * If NULL, then <New> will be added at the head of the + * list, else it will be added following <After>. + * + * Output: A pointer to the node that was inserted into the list (i.e., + * the same as <New>). + * + * ------------------------------------------------------------------------ ** + */ + +ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old ); + /* ------------------------------------------------------------------------ ** + * Remove a node from the list. + * + * Input: ListPtr - A pointer to the list from which <Old> is to be + * removed. + * Old - A pointer to the node that is to be removed from the + * list. + * + * Output: A pointer to the node that was removed (i.e., <Old>). + * + * ------------------------------------------------------------------------ ** + */ + + +/* ================================ The End ================================= */ +#endif /* ubi_dLinkList_H */ -- cgit From 1dafef88871338f06dbcbbb67ce3bbbb460d7bb6 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 16 Oct 1997 01:03:18 +0000 Subject: Made changes to the dir cache functions: - They now use the ubi_dLinkList linked list code. This is not a big gain, I suppose. It would be significant if there were lots of doubly-linked lists in the code and I replaced them all. The only other advantage is that the code is more modular, which appeals to my own sense of order, if no one elses. :-} - I allocate space for the entry structure and the strings in one go, instead of using malloc() and separate strdup() calls. This should be more efficient, and allows for a single call to free() to free the whole thing. These are very minor changes, but they do serve to make me more familiar with the code overall. --- source/smbd/dir.c | 204 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 83 deletions(-) diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 316b58818fd..d69ccfe1c19 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -628,97 +628,135 @@ int TellDir(void *p) } -static int dir_cache_size = 0; -static struct dir_cache { - struct dir_cache *next; - struct dir_cache *prev; - char *path; - char *name; - char *dname; - int snum; -} *dir_cache = NULL; +/* -------------------------------------------------------------------------- ** + * This section manages a global directory cache. + * (It should probably be split into a separate module. crh) + * -------------------------------------------------------------------------- ** + */ -/******************************************************************* -add an entry to the directory cache -********************************************************************/ -void DirCacheAdd(char *path,char *name,char *dname,int snum) -{ - int count; - struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry)); - if (!entry) return; - entry->path = strdup(path); - entry->name = strdup(name); - entry->dname = strdup(dname); - entry->snum = snum; - if (!entry->path || !entry->name || !entry->dname) return; - - entry->next = dir_cache; - entry->prev = NULL; - if (entry->next) entry->next->prev = entry; - dir_cache = entry; - - DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname)); - - if (dir_cache_size == DIRCACHESIZE) { - for (entry=dir_cache, count=1; - entry->next && count < dir_cache_size + 1; - entry=entry->next, count++) ; - if (entry->next || count != dir_cache_size + 1) { - DEBUG(0,("DirCache bug - please report %d %d\n",dir_cache_size,count)); - } - free(entry->path); - free(entry->name); - free(entry->dname); - if (entry->prev) entry->prev->next = entry->next; - free(entry); - } else { - dir_cache_size++; - } -} +#include "ubi_dLinkList.h" +typedef struct + { + ubi_dlNode node; + char *path; + char *name; + char *dname; + int snum; + } dir_cache_entry; + +static ubi_dlList dir_cache[1] = { { NULL, NULL, 0 } }; + +void DirCacheAdd( char *path, char *name, char *dname, int snum ) + /* ------------------------------------------------------------------------ ** + * Add an entry to the directory cache. + * + * Input: path - + * name - + * dname - + * snum - + * + * Output: None. + * + * ------------------------------------------------------------------------ ** + */ + { + int pathlen; + int namelen; + dir_cache_entry *entry; + + /* Allocate the structure & string space in one go so that it can be freed + * in one call to free(). + */ + pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */ + namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */ + entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry ) + + pathlen + + namelen + + strlen( dname ) +1 ); + if( NULL == entry ) /* Not adding to the cache is not fatal, */ + return; /* so just return as if nothing happened. */ + + /* Set pointers correctly and load values. */ + entry->path = strcpy( (char *)&entry[1], path); + entry->name = strcpy( &(entry->path[pathlen]), name); + entry->dname = strcpy( &(entry->name[namelen]), dname); + entry->snum = snum; + + /* Add the new entry to the linked list. */ + (void)ubi_dlAddHead( dir_cache, entry ); + DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) ); + + /* Free excess cache entries. */ + while( DIRCACHESIZE < dir_cache->count ) + free( ubi_dlRemTail( dir_cache ) ); + + } /* DirCacheAdd */ + + +char *DirCacheCheck( char *path, char *name, int snum ) + /* ------------------------------------------------------------------------ ** + * Search for an entry to the directory cache. + * + * Input: path - + * name - + * snum - + * + * Output: The dname string of the located entry, or NULL if the entry was + * not found. + * + * Notes: This uses a linear search, which is is okay because of + * the small size of the cache. Use a splay tree or hash + * for large caches. + * + * ------------------------------------------------------------------------ ** + */ + { + dir_cache_entry *entry; -/******************************************************************* -check for an entry in the directory cache -********************************************************************/ -char *DirCacheCheck(char *path,char *name,int snum) -{ - struct dir_cache *entry; - - for (entry=dir_cache; entry; entry=entry->next) { - if (entry->snum == snum && - strcmp(path,entry->path) == 0 && - strcmp(name,entry->name) == 0) { - DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); - return(entry->dname); + for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); + NULL != entry; + entry = (dir_cache_entry *)ubi_dlNext( entry ) ) + { + if( entry->snum == snum + && 0 == strcmp( name, entry->name ) + && 0 == strcmp( path, entry->path ) ) + { + DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); + return( entry->dname ); + } } - } return(NULL); -} + } /* DirCacheCheck */ + +void DirCacheFlush( int snum ) + /* ------------------------------------------------------------------------ ** + * Remove all cache entries which have an snum that matches the input. + * + * Input: snum - + * + * Output: None. + * + * ------------------------------------------------------------------------ ** + */ + { + dir_cache_entry *entry; + ubi_dlNodePtr next; -/******************************************************************* -flush entries in the dir_cache -********************************************************************/ -void DirCacheFlush(int snum) -{ - struct dir_cache *entry,*next; - - for (entry=dir_cache; entry; entry=next) { - if (entry->snum == snum) { - free(entry->path); - free(entry->dname); - free(entry->name); - next = entry->next; - if (entry->prev) entry->prev->next = entry->next; - if (entry->next) entry->next->prev = entry->prev; - if (dir_cache == entry) dir_cache = entry->next; - free(entry); - dir_cache_size--; - } else { - next = entry->next; + for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); NULL != entry; ) + { + next = ubi_dlNext( entry ); + if( entry->snum == snum ) + free( ubi_dlRemThis( dir_cache, entry ) ); + entry = (dir_cache_entry *)next; } - } -} + } /* DirCacheFlush */ + +/* -------------------------------------------------------------------------- ** + * End of the section that manages the global directory cache. + * -------------------------------------------------------------------------- ** + */ #ifdef REPLACE_GETWD -- cgit From 905b2b9562a8c82696d38024ec42aa38ca990277 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 16 Oct 1997 01:06:12 +0000 Subject: Don't need it any more. --- source/ubiqx/Makefile | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 source/ubiqx/Makefile diff --git a/source/ubiqx/Makefile b/source/ubiqx/Makefile deleted file mode 100644 index 369f7762bfe..00000000000 --- a/source/ubiqx/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -########################################################################### -# Makefile for ubiqx libraries under Samba. -# Copyright Chris Hertel & the Samba Team 1997 -########################################################################### - -.SUFFIXES: -.SUFFIXES: .c .o .h - -all: ubi_AVLtree.o ubi_BinTree.o ubi_SplayTree.o \ - ubi_dLinkList.o ubi_sLinkList.o - -ubi_BinTree.o: ubi_BinTree.h - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -ubi_AVLtree.o: ubi_AVLtree.h ubi_BinTree.h - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -ubi_SplayTree.o: ubi_SplayTree.h ubi_BinTree.h - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -ubi_dLinkList.o: ubi_dLinkList.h - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -ubi_sLinkList.o: ubi_sLinkList.h - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -.c.o: - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $*.c - -clean: - rm -f core *.o *~ -- cgit From 31d50db98bbb3b64400d432e386056f7963b7d8d Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Thu, 16 Oct 1997 01:13:09 +0000 Subject: Moved the LGPL from the ubiqx directory into the samba root directory and renamed it COPYING.LGPL. This is because the ubi_* files are under LGPL, not regular GPL. Removed the last few things from the ubiqx directory and deleted it. --- COPYING.LGPL | 481 +++++++++++++++++++++++++++++++++++++++++++++++++++ source/ubiqx/COPYING | 481 --------------------------------------------------- source/ubiqx/README | 20 --- 3 files changed, 481 insertions(+), 501 deletions(-) create mode 100644 COPYING.LGPL delete mode 100644 source/ubiqx/COPYING delete mode 100644 source/ubiqx/README diff --git a/COPYING.LGPL b/COPYING.LGPL new file mode 100644 index 00000000000..8c8377da464 --- /dev/null +++ b/COPYING.LGPL @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/source/ubiqx/COPYING b/source/ubiqx/COPYING deleted file mode 100644 index 8c8377da464..00000000000 --- a/source/ubiqx/COPYING +++ /dev/null @@ -1,481 +0,0 @@ - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the library, or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link a program with the library, you must provide -complete object files to the recipients so that they can relink them -with the library, after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -General Public License (also called "this License"). Each licensee is -addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also compile or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - c) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - d) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Library General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/source/ubiqx/README b/source/ubiqx/README deleted file mode 100644 index 84334906518..00000000000 --- a/source/ubiqx/README +++ /dev/null @@ -1,20 +0,0 @@ -This directory contains a set of utility modules that are being used with -Samba. The modules themselves do not require Samba, and may be used and -distributed independantly, under the terms of the GNU LIBRARY GENERAL -PUBLIC LICENSE (LGPL). A copy of LGPL should also be included in this -directory under the name COPYING. If this file is not present, you can -obtain a copy of the LGPL by writing to the Free Software Foundation, -Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -The modules included are: - -ubi_dLinkList - Simple doubly linked lists. -ubi_BinTree - Simple binary trees. -ubi_AVLtree - AVL height balanced binary trees (requires (ubi_BinTree). -ubi_SplayTree - Splay balanced binary trees (requires (ubi_BinTree). - -See http://www.interads.co.uk/~crh/ubiqx/ for more information. - -Chris Hertel -Samba Team -samba-bugs@samba.anu.edu.au -- cgit From ac50a88e1181bd4954f03e5450dedce87ed781ad Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 16 Oct 1997 03:53:07 +0000 Subject: fixed the problem that browsing breaks if you put quote marks around the server string option. I fixed it by adding: trim_string(ret, "\"", "\"") to lp_string() which means that it removes leading and trailing quotes from _all_ strings in smb.conf. I think this is what we want as I can't actually think of any case where quoted strings are needed. I suspect that this fix will actually fix browsing at quite a few sites. It's not uncommon to see people putting "" marks around the workgroup name or other essential strings. The real reason it was causing browsing to fail is that the browse.dat file uses " to delimit fields, which means that it wasn't being parsed correctly. It would be nice to use a proper database format in browse.dat sometime. In fact, we really need a generic database type subsystem in Samba to replace the mish-mash we currrently use (browse.dat, wins.dat, smbpasswd etc) --- source/param/loadparm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/param/loadparm.c b/source/param/loadparm.c index edc2d2b65f6..b8776500781 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -783,6 +783,8 @@ char *lp_string(char *s) else StrCpy(ret,s); + trim_string(ret, "\"", "\""); + standard_sub_basic(ret); return(ret); } -- cgit From 7b77784422ce80629a546b3eeb78f6fd5f425505 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 16 Oct 1997 03:57:40 +0000 Subject: fixed quote problem in 1.9.17 as well --- source/param/loadparm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 510a661dc39..398a9050d6a 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -779,6 +779,8 @@ char *lp_string(char *s) else StrCpy(ret,s); + trim_string(ret, "\"", "\""); + standard_sub_basic(ret); return(ret); } -- cgit From c84a043f89ccba001597962cd03e2f2a634c4b08 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Thu, 16 Oct 1997 05:33:24 +0000 Subject: Added Michael Johnsons' PAM modifications <johnsonm@redhat.com> This patch has been checked over. JHT --- source/smbd/password.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/smbd/password.c b/source/smbd/password.c index 1b1bd34bcca..9f4f0abcae8 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -416,33 +416,33 @@ static int PAM_conv (int num_msg, struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { - int count = 0, replies = 0; + int replies = 0; struct pam_response *reply = NULL; - int size = sizeof(struct pam_response); - #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ - if (!reply) return PAM_CONV_ERR; \ - size += sizeof(struct pam_response) #define COPY_STRING(s) (s) ? strdup(s) : NULL - for (count = 0; count < num_msg; count++) { - switch (msg[count]->msg_style) { + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) return PAM_CONV_ERR; + + for (replies = 0; replies < num_msg; replies++) { + switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_ON: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_username); + reply[replies].resp = COPY_STRING(PAM_username); /* PAM frees resp */ break; case PAM_PROMPT_ECHO_OFF: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_password); + reply[replies].resp = COPY_STRING(PAM_password); /* PAM frees resp */ break; case PAM_TEXT_INFO: + /* fall through */ + case PAM_ERROR_MSG: /* ignore it... */ + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; break; - case PAM_ERROR_MSG: default: /* Must be an error of some sort... */ free (reply); -- cgit From 921d2586cfda4f08a1ef3ea2f1502cfe1edd2bc4 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Thu, 16 Oct 1997 05:43:57 +0000 Subject: Added PAM patches submitted by <johnsonm@redhat.com> Checked over. OK. --- source/smbd/password.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/smbd/password.c b/source/smbd/password.c index 6d84a5ff61c..68205b4dae9 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -404,33 +404,33 @@ static int PAM_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { - int count = 0, replies = 0; + int replies = 0; struct pam_response *reply = NULL; - int size = sizeof(struct pam_response); - #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ - if (!reply) return PAM_CONV_ERR; \ - size += sizeof(struct pam_response) #define COPY_STRING(s) (s) ? strdup(s) : NULL - for (count = 0; count < num_msg; count++) { - switch (msg[count]->msg_style) { + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) return PAM_CONV_ERR; + + for (replies = 0; replies < num_msg; replies++) { + switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_ON: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_username); + reply[replies].resp = COPY_STRING(PAM_username); /* PAM frees resp */ break; case PAM_PROMPT_ECHO_OFF: - GET_MEM; reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_password); + reply[replies].resp = COPY_STRING(PAM_password); /* PAM frees resp */ break; case PAM_TEXT_INFO: + /* fall through */ + case PAM_ERROR_MSG: /* ignore it... */ + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; break; - case PAM_ERROR_MSG: default: /* Must be an error of some sort... */ free (reply); -- cgit From 8d53b35f22efabc79cc9d569875353501e900d60 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 16 Oct 1997 07:54:52 +0000 Subject: add ERRDOS/67 ERRnosuchshare to the client.c list of error strings --- source/client/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/client/client.c b/source/client/client.c index 4718db84ac0..cd9e8d1c97c 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -4765,6 +4765,7 @@ err_code_struct dos_msgs[] = { {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, + {"ERRnosuchshare", 67, "You specified an invalid share name"}, {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, {"ERRbadpipe",230,"Pipe invalid."}, {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, -- cgit From 1cccd7c519b8a706567477629bee70f7b7267b5c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Thu, 16 Oct 1997 08:01:00 +0000 Subject: add ERRDOS/67 ERRnosuchshare to the client.c list of error strings --- source/client/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/client/client.c b/source/client/client.c index 6d85bd8807f..98c77146916 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -4787,6 +4787,7 @@ err_code_struct dos_msgs[] = { {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, + {"ERRnosuchshare", 67, "You specified an invalid share name"}, {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, {"ERRbadpipe",230,"Pipe invalid."}, {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, -- cgit From eb81fae874383f77ad72c0f7686b8c49e645b0b8 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 16 Oct 1997 12:59:40 +0000 Subject: inside the auth 2 response bits, i wasn't storing the received client credentials for the calculation of the next credentials: i was storing the auth 2 calculated credentials. oops. --- source/pipenetlog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index d221b8e644e..4d28e3bef0f 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -374,9 +374,9 @@ static void api_lsa_auth_2( user_struct *vuser, /* create server challenge for inclusion in the reply */ cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred), srv_time, &srv_cred); - /* update the client credentials for use next time */ - memcpy(vuser->dc.clnt_cred.data, &(srv_cred.data), sizeof(srv_cred.data)); - memcpy(vuser->dc.srv_cred .data, &(srv_cred.data), sizeof(srv_cred.data)); + /* copy the received client credentials for use next time */ + memcpy(vuser->dc.clnt_cred.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data)); + memcpy(vuser->dc.srv_cred .data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data)); /* construct reply. */ *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata, -- cgit From dab35ce5d61d53bce6ede44e56d9393645c0d67e Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 16 Oct 1997 13:38:16 +0000 Subject: dealing with some stack overflow bug somewhere around the use of deal_with_credentials() by moving important code to the beginning of the function :-) :-) :-). the new seed (old_cred + time + 1) was getting corrupted. --- source/pipenetlog.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 4d28e3bef0f..32096b3b843 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -390,6 +390,17 @@ static BOOL deal_with_credentials(user_struct *vuser, UTIME new_clnt_time; uint32 new_cred; + DEBUG(5,("deal_with_credentials: %d\n", __LINE__)); + + /* increment client time by one second */ + new_clnt_time.time = clnt_cred->timestamp.time + 1; + + /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ + new_cred = IVAL(vuser->dc.clnt_cred.data, 0); + new_cred += new_clnt_time.time; + + DEBUG(5,("deal_with_credentials: new_cred[0]=%lx\n", new_cred)); + /* doesn't matter that server time is 0 */ srv_cred->timestamp.time = 0; @@ -400,25 +411,16 @@ static BOOL deal_with_credentials(user_struct *vuser, return False; } - /* increment client time by one second */ - new_clnt_time.time = clnt_cred->timestamp.time + 1; - DEBUG(5,("deal_with_credentials: new_clnt_time=%lx\n", new_clnt_time.time)); /* create server credentials for inclusion in the reply */ cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time, &(srv_cred->challenge)); - DEBUG(5,("deal_with_credentials: %d\n", __LINE__)); - DEBUG(5,("deal_with_credentials: clnt_cred[0]=%lx\n", vuser->dc.clnt_cred.data[0])); - new_cred = IVAL(vuser->dc.clnt_cred.data, 0); - new_cred += new_clnt_time.time; - - DEBUG(5,("deal_with_credentials: new_cred[0]=%lx\n", new_cred)); - + /* store new seed in client and server credentials */ SIVAL(vuser->dc.clnt_cred.data, 0, new_cred); SIVAL(vuser->dc.srv_cred .data, 0, new_cred); -- cgit From ce36bfb3e4ad4b72a9f9759a3c49d2a73175d249 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Thu, 16 Oct 1997 16:01:25 +0000 Subject: smb.h : id_info_1 has a pointer at the front of it. so does return credentials, and so does the client credentials. these are all from the sam logon. auth_level is 16 bytes not 32 and is actually called a switch_level. smbparse.c : smb_io_unihdr() - uni_max_len and uni_str_len are 16 bytes not 32. this may have a knock-on effect on smb_in_unihdr2() but we'll see... --- source/include/smb.h | 7 +++++-- source/smbparse.c | 45 +++++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 03cdc78e039..e4c2823a198 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -431,6 +431,7 @@ typedef struct clnt_info typedef struct clnt_info2 { DOM_CLNT_SRV login; + uint32 ptr_cred; DOM_CRED cred; } DOM_CLNT_INFO2; @@ -454,8 +455,9 @@ typedef struct arc4_owf_info /* DOM_ID_INFO_1 */ typedef struct id_info_1 { + uint32 ptr_id_info1; /* pointer to id_info_1 */ UNIHDR hdr_domain_name; /* domain name unicode header */ - uint32 param; /* param control */ + uint32 param_ctrl; /* param control */ DOM_LOGON_ID logon_id; /* logon ID */ UNIHDR hdr_user_name; /* user name unicode header */ UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ @@ -471,9 +473,10 @@ typedef struct id_info_1 typedef struct sam_info { DOM_CLNT_INFO2 client; + uint32 ptr_rtn_cred; /* pointer to return credentials */ DOM_CRED rtn_cred; /* return credentials */ uint16 logon_level; - uint32 auth_level; /* undocumented */ + uint16 switch_value; union { diff --git a/source/smbparse.c b/source/smbparse.c index 03ef5afe8e1..e5f455a4086 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -102,13 +102,10 @@ char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int de DEBUG(5,("%s%04x smb_io_unihdr\n", tab_depth(depth), PTR_DIFF(q, base))); depth++; - /* should be value 4, so enforce it. */ - hdr->undoc = 4; - q = align_offset(q, base, align); - DBG_RW_IVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 4; - DBG_RW_IVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 4; + DBG_RW_SVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 4; + DBG_RW_SVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 4; DBG_RW_IVAL("undoc ", depth, base, io, q, hdr->undoc ); q += 4; return q; @@ -340,6 +337,10 @@ char* smb_io_clnt_info2(BOOL io, DOM_CLNT_INFO2 *clnt, char *q, char *base, int q = align_offset(q, base, align); q = smb_io_clnt_srv(io, &(clnt->login), q, base, align, depth); + + q = align_offset(q, base, align); + + DBG_RW_IVAL("ptr_cred", depth, base, io, q, clnt->ptr_cred); q += 4; q = smb_io_cred (io, &(clnt->cred ), q, base, align, depth); return q; @@ -410,20 +411,25 @@ char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align q = align_offset(q, base, align); - q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align, depth); + DBG_RW_IVAL("ptr_id_info1", depth, base, io, q, id->ptr_id_info1); q += 4; - DBG_RW_IVAL("param", depth, base, io, q, id->param); q += 4; - q = smb_io_logon_id(io, &(id->logon_id), q, base, align, depth); + if (id->ptr_id_info1 != 0) + { + q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align, depth); + + DBG_RW_IVAL("param_ctrl", depth, base, io, q, id->param_ctrl); q += 4; + q = smb_io_logon_id(io, &(id->logon_id), q, base, align, depth); - q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align, depth); - q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align, depth); + q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align, depth); + q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align, depth); - q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align, depth); - q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align, depth); + q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align, depth); + q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align, depth); - q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align, depth); - q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align, depth); - q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align, depth); + q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align, depth); + q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align, depth); + q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align, depth); + } return q; } @@ -441,12 +447,14 @@ char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align q = align_offset(q, base, align); q = smb_io_clnt_info2(io, &(sam->client ), q, base, align, depth); + + DBG_RW_IVAL("ptr_rtn_cred", depth, base, io, q, sam->ptr_rtn_cred); q += 4; q = smb_io_cred (io, &(sam->rtn_cred), q, base, align, depth); - DBG_RW_IVAL("logon_level", depth, base, io, q, sam->logon_level); q += 4; - DBG_RW_SVAL("auth_level ", depth, base, io, q, sam->auth_level ); q += 4; + DBG_RW_SVAL("logon_level ", depth, base, io, q, sam->logon_level); q += 2; + DBG_RW_SVAL("switch_value", depth, base, io, q, sam->switch_value); q += 2; - switch (sam->auth_level) + switch (sam->switch_value) { case 1: { @@ -456,6 +464,7 @@ char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align default: { /* PANIC! */ + DEBUG(4,("smb_io_sam_info: unknown switch_value!\n")); break; } } -- cgit From 4b7d51ffb8cf23662e0e58a785620a0652da5a7c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 01:46:16 +0000 Subject: added -a "append log" option --- source/nmbd/nmbd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 3f0279908da..c7af54fa13b 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -493,7 +493,7 @@ static void usage(char *pname) signal(SIGHUP ,SIGNAL_CAST sig_hup); signal(SIGTERM,SIGNAL_CAST sig_term); - while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF) + while ((opt = getopt(argc, argv, "as:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF) { switch (opt) { @@ -524,6 +524,12 @@ static void usage(char *pname) pstrcpy(scope,optarg); strupper(scope); break; + case 'a': + { + extern BOOL append_log; + append_log = !append_log; + } + break; case 'D': is_daemon = True; break; -- cgit From 51182b915268ed1af516090a6230fb8eee252691 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 01:47:10 +0000 Subject: document -a "append log" option --- docs/manpages/nmbd.8 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8 index 148e53478c2..d66851570a6 100644 --- a/docs/manpages/nmbd.8 +++ b/docs/manpages/nmbd.8 @@ -186,6 +186,13 @@ The default log file is specified at compile time, typically as This option allows you to override the Netbios name that Samba uses for itself. .RE +.B \-a + +.RS 3 +If this parameter is specified, the log files will be appended to with each +new connection. By default, the log files will be overwritten. +.RE + .B \-p .I port number .RS 3 -- cgit From e02c21b0b8e3ed6f2d294458160c4f632af67ed3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 02:56:23 +0000 Subject: fix the handling of negative name query responses and the handling of packets with no answer section in general. The fix has 2 parts: 1) set ans_name to the name we queried if nmb->answers == NULL 2) check for nmb->answers == NULL in several other places where we currently check for nmb->answers->data While doing this, I noticed there are lots of places in our nmbd code where we make assumptions about the packets being well formed. Someone could easily implement a denial of service attack on nmbd by sending a packet that causes a null pointer dereference. Does anyone feel like going through the code and adding checks? Probably the best solution is to have a single function that "validates" a packet, making sure that all the required fields are there. This will be a bit tricky as what fields are required varies a lot between packets. A first pass would be a function that prints "SUSPECT PACKET" when it hits a packet that it suspects does not have a required field (or the field is badly formatted), then we could use this on a live system to find any cases we've missed. Any takers? --- source/nameservresp.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/source/nameservresp.c b/source/nameservresp.c index 8de90113fb6..deb56c0850e 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -59,7 +59,7 @@ static void response_name_release(struct nmb_name *ans_name, DEBUG(4,("response name release received\n")); - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) { /* IMPORTANT: see expire_netbios_response_entries() */ @@ -113,9 +113,9 @@ static void response_name_reg(struct nmb_name *ans_name, */ if ( ((d != wins_subnet) && (nmb->header.rcode == 6) && strequal(myworkgroup, name) && (type == 0x1b)) || - (nmb->header.rcode == 0 && nmb->answers->rdata)) + (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata)) #else - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) #endif { /* IMPORTANT: see expire_netbios_response_entries() */ @@ -154,7 +154,7 @@ static void response_server_check(struct nmb_name *ans_name, we sent to - rather than reading the response. */ - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) putip((char*)&send_ip,&nmb->answers->rdata[2]); else { @@ -269,7 +269,8 @@ static void response_name_status_check(struct in_addr ip, struct nmb_name name; fstring serv_name; - if (interpret_node_status(d,nmb->answers->rdata, + if (nmb->answers && + interpret_node_status(d,nmb->answers->rdata, &name,0x20,serv_name,ip,bcast)) { if (*serv_name) @@ -311,7 +312,7 @@ static void response_name_query_register(struct nmb_packet *nmb, return; } - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) { /* we had sent out a name query to the current owner of a name because someone else wanted it. now they @@ -388,7 +389,7 @@ static void response_name_query_sync(struct nmb_packet *nmb, return; } - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) { int nb_flags = nmb->answers->rdata[0]; struct in_addr found_ip; @@ -464,7 +465,7 @@ for %s\n", nmb->header.rcode == 0 ? "success" : "failure", /* Check the name is correct and ip address returned is our own. If it is then we just remove the response record. */ - if (name_equal(&n->name, ans_name) && (nmb->header.rcode == 0) && (nmb->answers->rdata)) + if (name_equal(&n->name, ans_name) && (nmb->header.rcode == 0) && nmb->answers && (nmb->answers->rdata)) { struct in_addr found_ip; @@ -576,7 +577,7 @@ static BOOL response_problem_check(struct response_record *n, { if (n->num_msgs > 1) { - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (nmb->header.rcode == 0 && nmb->answers && nmb->answers->rdata) { int nb_flags = nmb->answers->rdata[0]; @@ -822,27 +823,25 @@ void response_netbios_packet(struct packet_struct *p) DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip))); } - if (nmb->answers == NULL) - { - /* hm. the packet received was a response, but with no answer. wierd! */ - DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), BOOLSTR(bcast))); - return; - } + if (nmb->answers == NULL) { + /* if there is no name is the response then the name is the one + we queried on */ + ans_name = &n->name; + } else { + ans_name = &nmb->answers->rr_name; + debug_rr_type(nmb->answers->rr_type); + } - ans_name = &nmb->answers->rr_name; DEBUG(3,("response for %s from %s(%d) (bcast=%s)\n", namestr(ans_name), inet_ntoa(p->ip), p->port, BOOLSTR(bcast))); - debug_rr_type(nmb->answers->rr_type); - n->num_msgs++; /* count number of responses received */ n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */ debug_state_type(n->state); /* problem checking: multiple responses etc */ - if (response_problem_check(n, nmb, ans_name->name)) + if (nmb->answers && response_problem_check(n, nmb, ans_name->name)) return; /* now deal with the current state */ -- cgit From 42cb21d7259acfca124e5310894fb4fb8df4ad0c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 03:09:03 +0000 Subject: remove a spurious error message from nmbd. The message was: WINS server did not respond to name registration! this messages should only be produced when we are trying to register our own names, not when we are the one with the name database and we are doing a NAME_REGISTER_CHALLENGE on behalf of another host (for secured wins registration) --- source/nameresp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/nameresp.c b/source/nameresp.c index c40dd16a888..2e625735c49 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -118,12 +118,6 @@ static void dead_netbios_entry(struct subnet_record *d, add_name_respond(d,n->fd,d->myip, n->reply_id ,&n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip, True, n->reply_to_ip); - - if (!n->bcast && n->num_msgs == 0) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } break; } -- cgit From f9fbcad42ec20da56466054e1984e391d03b3204 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 17 Oct 1997 11:54:30 +0000 Subject: set the wrong info level (0x0C00 0000 instead of 0xC000 0000) so that nt got confused and thought that the server password had been set instead of refused. this is for the SRV_PWSET response. --- source/pipenetlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 32096b3b843..54769270afe 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -446,7 +446,7 @@ static void api_lsa_srv_pwset( user_struct *vuser, /* construct reply. always indicate failure. nt keeps going... */ *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata, &srv_cred, - NT_STATUS_WRONG_PASSWORD|0xC000000); + NT_STATUS_WRONG_PASSWORD|0xC0000000); } -- cgit From 71c6678cd7ffe30a5da27766cf99147e1921feae Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 17 Oct 1997 13:43:01 +0000 Subject: smbparse.c smb.h : uni_max_len and uni_str_len are the other way round, in UNIHDR. util.c : increased the show_msg() data size from 256 bytes to 512 bytes: the LSA SAM Logon response can be about 500 bytes long. pipenetlog.c : forgot to set the authoritative field to 1. --- source/include/smb.h | 2 +- source/lib/util.c | 6 +++--- source/pipenetlog.c | 1 + source/pipeutil.c | 10 ++++++++++ source/smbparse.c | 8 ++++++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index e4c2823a198..80b2f28f4a5 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -772,7 +772,7 @@ typedef struct lsa_q_user_info UNIHDR hdr_logon_dom; /* logon domain unicode string header */ uint32 buffer_dom_id; /* undocumented logon domain id pointer */ - char padding[40]; /* unused padding bytes? */ + char padding[40]; /* unused padding bytes. expansion room */ uint32 num_other_sids; /* 0 - num_sids */ uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */ diff --git a/source/lib/util.c b/source/lib/util.c index 0a8540b48b4..a82713a0d84 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -1182,9 +1182,9 @@ void show_msg(char *buf) DEBUG(5,("smb_bcc=%d\n",bcc)); if (DEBUGLEVEL < 10) return; - for (i = 0; i < MIN(bcc, 256); i += 16) + for (i = 0; i < MIN(bcc, 512); i += 16) { - for (j = 0; j < 16 && i+j < MIN(bcc,256); j++) + for (j = 0; j < 16 && i+j < MIN(bcc,512); j++) { DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j))); @@ -1193,7 +1193,7 @@ void show_msg(char *buf) } DEBUG(10,(" ")); - for (j = 0; j < 16 && i+j < MIN(bcc,256); j++) + for (j = 0; j < 16 && i+j < MIN(bcc,512); j++) { unsigned char c = CVAL(smb_buf(buf),i+j); if (c < 32 || c > 128) c = '.'; diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 54769270afe..14b20639514 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -242,6 +242,7 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, r_s.user = user_info; r_s.buffer_user = user_info != NULL ? 1 : 0; r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); + r_s.auth_resp = 1; /* authoritative response */ /* store the response in the SMB stream */ q = lsa_io_r_sam_logon(False, &r_s, q, base, 4, 0); diff --git a/source/pipeutil.c b/source/pipeutil.c index f55a8d2181e..de58d56a98c 100644 --- a/source/pipeutil.c +++ b/source/pipeutil.c @@ -106,6 +106,16 @@ void make_dom_sid(DOM_SID *sid, char *domsid) int identauth; char *p; + if (sid == NULL) return; + + if (domsid == NULL) + { + DEBUG(4,("netlogon domain SID: none\n")); + sid->sid_no = 0; + sid->num_auths = 0; + return; + } + DEBUG(4,("netlogon domain SID: %s\n", domsid)); /* assume, but should check, that domsid starts "S-" */ diff --git a/source/smbparse.c b/source/smbparse.c index e5f455a4086..de6ee7b90ee 100644 --- a/source/smbparse.c +++ b/source/smbparse.c @@ -104,10 +104,14 @@ char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int de q = align_offset(q, base, align); - DBG_RW_SVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 4; - DBG_RW_SVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 4; + DBG_RW_SVAL("uni_str_len", depth, base, io, q, hdr->uni_str_len); q += 2; + DBG_RW_SVAL("uni_max_len", depth, base, io, q, hdr->uni_max_len); q += 2; DBG_RW_IVAL("undoc ", depth, base, io, q, hdr->undoc ); q += 4; + /* oops! XXXX maybe issue a warning that this is happening... */ + if (hdr->uni_max_len > MAX_UNISTRLEN) hdr->uni_max_len = MAX_UNISTRLEN; + if (hdr->uni_str_len > MAX_UNISTRLEN) hdr->uni_str_len = MAX_UNISTRLEN; + return q; } -- cgit From 7993e17c9a1edddae6407d3f12790c461def705a Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 17 Oct 1997 16:46:56 +0000 Subject: pipenetlog.c lsaparse.c smb.h : SAM logon sorting. too many buffer pointers. added in the missing switch value (value of 3). dealing with the buffer pointers to the user info structure in a slightly different way. --- source/include/smb.h | 4 +- source/libsmb/credentials.c | 11 ++++- source/lsaparse.c | 116 ++++++++++++++++++++++---------------------- source/pipenetlog.c | 30 ++++++++---- 4 files changed, 90 insertions(+), 71 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 80b2f28f4a5..11ec6940a66 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -741,7 +741,7 @@ typedef struct lsa_r_srv_pwset_info /* LSA_USER_INFO */ typedef struct lsa_q_user_info { - uint32 undoc_buffer; + uint32 ptr_user_info; NTTIME logon_time; /* logon time */ NTTIME logoff_time; /* logoff time */ @@ -809,7 +809,7 @@ typedef struct lsa_r_sam_logon_info uint32 buffer_creds; /* undocumented buffer pointer */ DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - uint32 buffer_user; + uint16 switch_value; /* 3 - indicates type of USER INFO */ LSA_USER_INFO *user; uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index d56598e98a3..8881704a7a8 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -130,6 +130,15 @@ int cred_assert(DOM_CHAL *cred, uint32 session_key[2], DOM_CHAL *stored_cred, DEBUG(5,(" challenge : %lx %lx\n", cred->data[0], cred->data[1])); DEBUG(5,(" calculated: %lx %lx\n", cred2.data[0], cred2.data[1])); - return memcmp(cred->data, cred2.data, 8) == 0; + if (memcmp(cred->data, cred2.data, 8) == 0) + { + DEBUG(5, ("credentials check ok\n")); + return True; + } + else + { + DEBUG(5, ("credentials check wrong\n")); + return False; + } } diff --git a/source/lsaparse.c b/source/lsaparse.c index aed110f1b45..ae3d06faac9 100644 --- a/source/lsaparse.c +++ b/source/lsaparse.c @@ -368,63 +368,66 @@ char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int ali q = align_offset(q, base, align); - DBG_RW_IVAL("undoc_buffer ", depth, base, io, q, usr->undoc_buffer); q += 4; + DBG_RW_IVAL("ptr_user_info ", depth, base, io, q, usr->ptr_user_info); q += 4; - q = smb_io_time(io, &(usr->logon_time) , q, base, align, depth); /* logon time */ - q = smb_io_time(io, &(usr->logoff_time) , q, base, align, depth); /* logoff time */ - q = smb_io_time(io, &(usr->kickoff_time) , q, base, align, depth); /* kickoff time */ - q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align, depth); /* password last set time */ - q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align, depth); /* password can change time */ - q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align, depth); /* password must change time */ - - q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align, depth); /* username unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align, depth); /* user's full name unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align, depth); /* logon script unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align, depth); /* profile path unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align, depth); /* home directory unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align, depth); /* home directory drive unicode string header */ - - DBG_RW_SVAL("logon_count. ", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ - DBG_RW_SVAL("bad_pw_count ", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ - - DBG_RW_IVAL("user_id ", depth, base, io, q, usr->user_id ); q += 4; /* User ID */ - DBG_RW_IVAL("group_id ", depth, base, io, q, usr->group_id ); q += 4; /* Group ID */ - DBG_RW_IVAL("num_groups ", depth, base, io, q, usr->num_groups ); q += 4; /* num groups */ - DBG_RW_IVAL("buffer_groups ", depth, base, io, q, usr->buffer_groups); q += 4; /* undocumented buffer pointer to groups. */ - DBG_RW_IVAL("user_flgs ", depth, base, io, q, usr->user_flgs ); q += 4; /* user flags */ - - DBG_RW_PCVAL("sess_key ", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ - - q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align, depth); /* logon server unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align, depth); /* logon domain unicode string header */ - - DBG_RW_IVAL("buffer_dom_id ", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ - DBG_RW_PCVAL("padding ", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ - - DBG_RW_IVAL("num_other_sids", depth, base, io, q, usr->num_other_sids); q += 4; /* 0 - num_sids */ - DBG_RW_IVAL("buffer_other_sids", depth, base, io, q, usr->buffer_other_sids); q += 4; /* NULL - undocumented pointer to SIDs. */ - - q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align, depth); /* username unicode string */ - q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align, depth); /* user's full name unicode string */ - q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align, depth); /* logon script unicode string */ - q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align, depth); /* profile path unicode string */ - q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align, depth); /* home directory unicode string */ - q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align, depth); /* home directory drive unicode string */ - - DBG_RW_IVAL("num_groups2 ", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ - for (i = 0; i < usr->num_groups2; i++) + if (usr->ptr_user_info != 0) { - q = smb_io_gid(io, &(usr->gids[i]), q, base, align, depth); /* group info */ - } + q = smb_io_time(io, &(usr->logon_time) , q, base, align, depth); /* logon time */ + q = smb_io_time(io, &(usr->logoff_time) , q, base, align, depth); /* logoff time */ + q = smb_io_time(io, &(usr->kickoff_time) , q, base, align, depth); /* kickoff time */ + q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align, depth); /* password last set time */ + q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align, depth); /* password can change time */ + q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align, depth); /* password must change time */ + + q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align, depth); /* username unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align, depth); /* user's full name unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align, depth); /* logon script unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align, depth); /* profile path unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align, depth); /* home directory unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align, depth); /* home directory drive unicode string header */ + + DBG_RW_SVAL("logon_count ", depth, base, io, q, usr->logon_count ); q += 2; /* logon count */ + DBG_RW_SVAL("bad_pw_count ", depth, base, io, q, usr->bad_pw_count); q += 2; /* bad password count */ + + DBG_RW_IVAL("user_id ", depth, base, io, q, usr->user_id ); q += 4; /* User ID */ + DBG_RW_IVAL("group_id ", depth, base, io, q, usr->group_id ); q += 4; /* Group ID */ + DBG_RW_IVAL("num_groups ", depth, base, io, q, usr->num_groups ); q += 4; /* num groups */ + DBG_RW_IVAL("buffer_groups ", depth, base, io, q, usr->buffer_groups); q += 4; /* undocumented buffer pointer to groups. */ + DBG_RW_IVAL("user_flgs ", depth, base, io, q, usr->user_flgs ); q += 4; /* user flags */ + + DBG_RW_PCVAL("sess_key ", depth, base, io, q, usr->sess_key, 16); q += 16; /* unused user session key */ + + q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align, depth); /* logon server unicode string header */ + q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align, depth); /* logon domain unicode string header */ + + DBG_RW_IVAL("buffer_dom_id ", depth, base, io, q, usr->buffer_dom_id); q += 4; /* undocumented logon domain id pointer */ + DBG_RW_PCVAL("padding ", depth, base, io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ + + DBG_RW_IVAL("num_other_sids", depth, base, io, q, usr->num_other_sids); q += 4; /* 0 - num_sids */ + DBG_RW_IVAL("buffer_other_sids", depth, base, io, q, usr->buffer_other_sids); q += 4; /* NULL - undocumented pointer to SIDs. */ + + q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align, depth); /* username unicode string */ + q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align, depth); /* user's full name unicode string */ + q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align, depth); /* logon script unicode string */ + q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align, depth); /* profile path unicode string */ + q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align, depth); /* home directory unicode string */ + q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align, depth); /* home directory drive unicode string */ + + DBG_RW_IVAL("num_groups2 ", depth, base, io, q, usr->num_groups2); q += 4; /* num groups */ + for (i = 0; i < usr->num_groups2; i++) + { + q = smb_io_gid(io, &(usr->gids[i]), q, base, align, depth); /* group info */ + } - q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align, depth); /* logon server unicode string */ - q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align, depth); /* logon domain unicode string */ + q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align, depth); /* logon server unicode string */ + q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align, depth); /* logon domain unicode string */ - q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align, depth); /* domain SID */ + q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align, depth); /* domain SID */ - for (i = 0; i < usr->num_other_sids; i++) - { - q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align, depth); /* other domain SIDs */ + for (i = 0; i < usr->num_other_sids; i++) + { + q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align, depth); /* other domain SIDs */ + } } return q; @@ -462,12 +465,9 @@ char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int DBG_RW_IVAL("buffer_creds", depth, base, io, q, r_l->buffer_creds); q += 4; /* undocumented buffer pointer */ q = smb_io_cred(io, &(r_l->srv_creds), q, base, align, depth); /* server credentials. server time stamp appears to be ignored. */ - DBG_RW_IVAL("buffer_user ", depth, base, io, q, r_l->buffer_user); q += 4; - if (r_l->buffer_user != 0) - { - q = lsa_io_user_info(io, r_l->user, q, base, align, depth); - } - + DBG_RW_SVAL("switch_value", depth, base, io, q, r_l->switch_value); q += 2; /* 1 - Authoritative response; 0 - Non-Auth? */ + q = align_offset(q, base, align); + q = lsa_io_user_info(io, r_l->user, q, base, align, depth); DBG_RW_IVAL("auth_resp ", depth, base, io, q, r_l->auth_resp); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ DBG_RW_IVAL("status ", depth, base, io, q, r_l->status); q += 4; diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 14b20639514..f2916207969 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -164,7 +164,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, int len_logon_srv = strlen(logon_srv); int len_logon_dom = strlen(logon_dom); - usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ + usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */ usr->logon_time = *logon_time; usr->logoff_time = *logoff_time; @@ -186,7 +186,7 @@ static void make_lsa_user_info(LSA_USER_INFO *usr, usr->user_id = user_id; usr->group_id = group_id; usr->num_groups = num_groups; - usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ + usr->buffer_groups = 1; /* indicates fill in groups, below, even if there are none */ usr->user_flgs = user_flgs; if (sess_key != NULL) @@ -240,8 +240,17 @@ static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, /* store the user information, if there is any. */ r_s.user = user_info; - r_s.buffer_user = user_info != NULL ? 1 : 0; - r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); + if (user_info != NULL && user_info->ptr_user_info != 0) + { + r_s.switch_value = 3; /* indicates type of validation user info */ + r_s.status = 0; + } + else + { + r_s.switch_value = 0; /* don't know what this value is supposed to be */ + r_s.status = 0xC000000|NT_STATUS_NO_SUCH_USER; + } + r_s.auth_resp = 1; /* authoritative response */ /* store the response in the SMB stream */ @@ -406,7 +415,7 @@ static BOOL deal_with_credentials(user_struct *vuser, srv_cred->timestamp.time = 0; /* check that the client credentials are valid */ - if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, + if (!cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key, &(vuser->dc.clnt_cred), clnt_cred->timestamp)) { return False; @@ -478,7 +487,6 @@ static void api_lsa_sam_logon( user_struct *vuser, { LSA_Q_SAM_LOGON q_l; LSA_USER_INFO usr_info; - LSA_USER_INFO *p_usr_info = NULL; DOM_CRED srv_creds; @@ -523,9 +531,7 @@ static void api_lsa_sam_logon( user_struct *vuser, standard_sub_basic(home_dir); #endif - p_usr_info = &usr_info; - - make_lsa_user_info(p_usr_info, + make_lsa_user_info(&usr_info, &dummy_time, /* logon_time */ &dummy_time, /* logoff_time */ @@ -558,9 +564,13 @@ static void api_lsa_sam_logon( user_struct *vuser, dom_sid, /* char *dom_sid */ NULL); /* char *other_sids */ } + else + { + usr_info.ptr_user_info = 0; + } *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata, - &srv_creds, p_usr_info); + &srv_creds, &usr_info); } -- cgit From f3018fec0d9b0574d9221b934b0fd515d17bd6db Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Fri, 17 Oct 1997 17:05:12 +0000 Subject: locking.c: Fix for zero length share files from Gerald Werner <wernerg@mfldclin.edu> plus a mod to remove a race condition. nameservresp.c: Improved debug message. proto.h: The usuual. Jeremy (jallison@whistle.com) --- source/locking/locking.c | 65 +++++++++++++++++++++++++++++++++--------------- source/nameservresp.c | 3 ++- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/source/locking/locking.c b/source/locking/locking.c index 461ad5aef0b..559c7284b36 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -597,6 +597,26 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) return(True); } +/******************************************************************* +Force a share file to be deleted. +********************************************************************/ +static int delete_share_file( int cnum, char *fname ) +{ + /* the share file could be owned by anyone, so do this as root */ + become_root(0); + + if(unlink(fname) != 0) { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } else { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + unbecome_root(0); + + return 0; +} + /******************************************************************* lock a share mode file. ******************************************************************/ @@ -695,6 +715,31 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok { int fd = (int)token; int ret = True; + struct stat sb; + pstring fname; + + /* Fix for zero length share files from + Gerald Werner <wernerg@mfldclin.edu> */ + + share_name(cnum, dev, inode, fname); + + /* get the share mode file size */ + if(fstat((int)token, &sb) != 0) + { + DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + sb.st_size = 1; + ret = False; + } + + /* If the file was zero length, we must delete before + doing the unlock to avoid a race condition (see + the code in lock_share_mode_entry for details. + */ + + /* remove the share file if zero length */ + if(sb.st_size == 0) + delete_share_file(cnum, fname); /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ @@ -709,26 +754,6 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok return ret; } -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ -static int delete_share_file( int cnum, char *fname ) -{ - /* the share file could be owned by anyone, so do this as root */ - become_root(0); - - if(unlink(fname) != 0) { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } else { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - unbecome_root(0); - - return 0; -} - /******************************************************************* Read a share file into a buffer. ********************************************************************/ diff --git a/source/nameservresp.c b/source/nameservresp.c index 8de90113fb6..5ab70d7a4de 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -805,7 +805,8 @@ void response_netbios_packet(struct packet_struct *p) struct subnet_record *d = NULL; if (!(n = find_response_record(&d,nmb->header.name_trn_id))) { - DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n")); + DEBUG(2,("unknown netbios response id %d (received late or from nmblookup?)\n", + nmb->header.name_trn_id)); return; } -- cgit From 4c99a083b9555b1ccf16faf0d4c1fba8f52bbb6a Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Fri, 17 Oct 1997 17:59:38 +0000 Subject: make_unihdr() was setting the length to 1/2 the required value. --- source/pipeutil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/pipeutil.c b/source/pipeutil.c index de58d56a98c..9a5e4deedd8 100644 --- a/source/pipeutil.c +++ b/source/pipeutil.c @@ -173,8 +173,8 @@ int make_rpc_reply(char *inbuf, char *q, int data_len) void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) { - hdr->uni_max_len = max_len; - hdr->uni_str_len = len; + hdr->uni_max_len = 2 * max_len; + hdr->uni_str_len = 2 * len; hdr->undoc = terminate; } -- cgit From cb51c860b352fb9d07fb3298d0317274ba6c9925 Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" <crh@samba.org> Date: Fri, 17 Oct 1997 21:06:20 +0000 Subject: Simply moved the #include for ubi_dLinkList.h from within dir.c to includes.h. More consistent with current practice. --- source/include/includes.h | 1 + source/smbd/dir.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/include/includes.h b/source/include/includes.h index a877f1ffb35..ce02b8a02a7 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -117,6 +117,7 @@ by the previous section */ #include "local.h" +#include "ubi_dLinkList.h" #include <stdio.h> #ifdef POSIX_STDLIBH #include <posix/stdlib.h> diff --git a/source/smbd/dir.c b/source/smbd/dir.c index d69ccfe1c19..c12305499a5 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -634,8 +634,6 @@ int TellDir(void *p) * -------------------------------------------------------------------------- ** */ -#include "ubi_dLinkList.h" - typedef struct { ubi_dlNode node; -- cgit From c24765317c08f67b9a7f814fbe89bed31cdbf49e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 22:32:45 +0000 Subject: A lot of changes to the example smb.conf file. As I discussed with John, I really didn't like having "dangerous" options in here. --- examples/smb.conf.default | 240 ++++++++++++++++++++++------------------------ 1 file changed, 115 insertions(+), 125 deletions(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index a815a29011f..c11594e6fc9 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -1,180 +1,169 @@ -; The global setting for a default install -; Copyright(C) John H Terpstra - 1997 -;======================= Global Settings ===================================== +;; This is the main Samba configuration file. You should read the +;; smb.conf(5) manual page in order to understand the options listed +;; here. Samba has a huge number of configurable options (perhaps too +;; many!) most of which are not shown in this example + +;; Any line which starts with a ; (semi-colon) is a comment and +;; is ignored + + +;;======================= Global Settings ===================================== [global] -; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 - workgroup = WORKGROUP +;; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 + workgroup = MYGROUP -; comment is the equivalent of the NT Description field - comment = Samba Server +;; server string is the equivalent of the NT Description field + server string = Samba Server -; printing = BSD or SYSV or AIX, etc. - printing = bsd +;; This option is important for security. It allows you to restrict +;; connections to machines which are on your local network. The +;; following example restricts access to two C class networks and +;; the "loopback" interface. For more examples of the syntax see +;; the smb.conf man page +; hosts allow = 192.168.1. 192.168.2. 127. + +;; if you want to automatically load your printer list rather +;; than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes -; Uncomment this if you want a guest account, you must add this to /etc/passwd +;; Uncomment this if you want a guest account, you must add this to /etc/passwd +;; otherwise the user "nobody" is used ; guest account = pcguest + +;; this tells Samba to use a separate log file for each machine +;; that connects log file = /usr/local/samba/var/log.%m -; Put a capping on the size of the log files (in Kb) +;; Put a capping on the size of the log files (in Kb). max log size = 50 -; Options for handling file name case sensitivity and / or preservation -; Case Sensitivity breaks many WfW and Win95 apps -; case sensitive = yes - short preserve case = yes - preserve case = yes - -; Security and file integrity related options - lock directory = /usr/local/samba/var/locks - locking = yes -; Strict locking is available for paranoid locking situations only -; enabling this severely degrades read / write performance. -; strict locking = yes -; fake oplocks = yes - share modes = yes - -; Security modes: USER uses Unix username/passwd, SHARE uses WfW type passwords -; SERVER uses an other SMB server (eg: Windows NT Server or Samba) -; to provide authentication services +;; Security mode. Most people will want user level security. See +;; security_level.txt for details. security = user -; Use password server option only with security = server +;; Use password server option only with security = server ; password server = <NT-Server-Name> -; Configuration Options ***** The location of this entry in your smb.conf -; heirachy determines which parameters are overwritten - please watch out! -; Where %m is any SMBName (machine name, or computer name) for which a custom -; configuration is desired +;; Using the following line enables you to customise your configuration +;; on a per machine basis. The %m gets replaced with the netbios name +;; of the machine that is connecting ; include = /usr/local/samba/lib/smb.conf.%m -; Performance Related Options -; Before setting socket options read the smb.conf man page!! +;; Most people will find that this option gives better performance. +;; See speed.txt and the manual pages for details socket options = TCP_NODELAY -; Socket Address is used to specify which socket Samba -; will listen on (good for aliased systems) -; socket address = aaa.bbb.ccc.ddd -; Use keep alive only if really needed!!!! -; keep alive = 60 -; Configure Samba to use multiple interfaces -; Samba will auto-detect network interfaces - only use this if -; the auto-detection does not deliver the needed results -; interfaces = 192.168.12.2/24 176.16.111.22/19 10.11.13.14/255.255.252.0 - -; Browser Control Options: -; Local Master set to True causes Samba to participate in browser elections -; the default setting is true, this causes Samba to behave like a -; Windows NT server. Setting this to false turns off all browser -; election participation. -; local master = yes - -; OS Level gives Samba the power to win browser elections. Windows NT = 32 -; Any value < 32 means NT wins as Master Browser, > 32 Samba gets it -; default = 0, this ensures that Samba will NOT win the browser election. + +;; Configure Samba to use multiple interfaces +;; If you have multiple network interfaces then you must list them +;; here. See the man page for details. +; interfaces = 192.168.12.2/24 192.168.13.2/24 + +;; Browser Control Options: +;; set local master to no if you don't want Samba to become a master +;; browser on your network. Otherwise the normal election rules apply +; local master = no + +;; OS Level determines the precedence of this server in master browser +;; elections. The default value should be reasonable ; os level = 33 -; Domain Master specifies Samba to be the Domain Master Browser -; Only ever set this if there is NO Windows NT Domain Controller on the -; network +;; Domain Master specifies Samba to be the Domain Master Browser. This +;; allows Samba to collate browse lists between subnets. Don't use this +;; if you already have a Windows NT domain controller doing this job ; domain master = yes -; Preferred Master causes Samba to force a local browser election on startup +;; Preferred Master causes Samba to force a local browser election on startup +;; and gives it a slightly higher chance of winning the election ; preferred master = yes -; Use with care only if you have an NT server on your network that has been -; configured at install time to be a primary domain controller. +;; Use only if you have an NT server on your network that has been +;; configured at install time to be a primary domain controller. ; domain controller = <NT-Domain-Controller-SMBName> -; Domain Logon Service Options: -; Domain logon control can be a good thing! See [netlogon] share section below! -; Do NOT set this to yes if there is an Windows NT domain controller -; on the network +;; Enable this if you want Samba to be a domain logon server for +;; Windows95 workstations. ; domain logons = yes -; run a specific logon batch file per workstation (machine) +;; if you enable domain logons then you may want a per-machine or +;; per user logon script +;; run a specific logon batch file per workstation (machine) ; logon script = %m.bat -; run a specific logon batch file per username +;; run a specific logon batch file per username ; logon script = %u.bat -; Where to store roving profiles (only for Win95 and WinNT) -; %L substitutes for the SMB name we are called, %U is username -; You must uncomment the [Profiles] share below +;; Where to store roving profiles (only for Win95 and WinNT) +;; %L substitutes for this servers netbios name, %U is username +;; You must uncomment the [Profiles] share below ; logon path = \\%L\Profiles\%U -; Windows Internet Name Serving Support Section: -; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server -; the default is NO. If you have an Windows NT Server WINS use it! -; Samba defaults to wins support = no +;; Windows Internet Name Serving Support Section: +;; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server ; wins support = yes -; WINS Server - Tells the NMBD components of Samba to be a WINS Client -; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both +;; WINS Server - Tells the NMBD components of Samba to be a WINS Client +;; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both ; wins server = w.x.y.z -; WINS Proxy - Tells Samba to answer name resolution queries on behalf of a non -; WINS Client capable client, for this to work there must be at least one -; WINS Server on the network. The default is NO. +;; WINS Proxy - Tells Samba to answer name resolution queries on +;; behalf of a non WINS capable client, for this to work there must be +;; at least one WINS Server on the network. The default is NO. ; wins proxy = yes -;============================ Share Definitions ============================== +;;============================ Share Definitions ============================== [homes] comment = Home Directories browseable = no writable = yes -; Un-comment the following and create the netlogon directory for Domain Logons +;; Un-comment the following and create the netlogon directory for Domain Logons ; [netlogon] -; comment = Samba Network Logon Service +; comment = Network Logon Service ; path = /usr/local/samba/lib/netlogon -; Case sensitivity breaks logon script processing!!! -; case sensitive = no ; guest ok = yes -; locking = no ; writable = no -; For browseable say NO if you want to hide the NETLOGON share -; browseable = yes -; Un-comment the following to provide a specific roving profile share -; the default is to use the user's home directory + +;; Un-comment the following to provide a specific roving profile share +;; the default is to use the user's home directory ;[Profiles] ; path = /usr/local/samba/profiles ; browseable = no -; printable = no ; guest ok = yes -; NOTE: There is NO need to specifically define each individual printer + +;; NOTE: If you have a BSD-style print system there is no need to +;; specifically define each individual printer [printers] comment = All Printers path = /usr/spool/samba browseable = no - printable = yes -; Set public = yes to allow user 'guest account' to print +;; Set public = yes to allow user 'guest account' to print guest ok = no writable = no - create mask = 0700 +;; This one is useful for people to share files ;[tmp] ; comment = Temporary file space ; path = /tmp ; read only = no ; public = yes -; A publicly accessible directory, but read only, except for people in -; the staff group -[public] - comment = Public Stuff - path = /home/samba - public = yes - writable = yes - printable = no - write list = @users +;; A publicly accessible directory, but read only, except for people in +;; the staff group +;[public] +; comment = Public Stuff +; path = /home/samba +; public = yes +; writable = yes +; printable = no +; write list = @users -; Other examples. -; -; A private printer, usable only by fred. Spool data will be placed in fred's -; home directory. Note that fred must have write access to the spool directory, -; wherever it is. +;; Other examples. +;; +;; A private printer, usable only by fred. Spool data will be placed in fred's +;; home directory. Note that fred must have write access to the spool directory, +;; wherever it is. ;[fredsprn] ; comment = Fred's Printer ; valid users = fred @@ -184,8 +173,8 @@ ; writable = no ; printable = yes ; -; A private directory, usable only by fred. Note that fred requires write -; access to the directory. +;; A private directory, usable only by fred. Note that fred requires write +;; access to the directory. ;[fredsdir] ; comment = Fred's Service ; path = /usr/somewhere/private @@ -194,10 +183,10 @@ ; writable = yes ; printable = no ; -; a service which has a different directory for each machine that connects -; this allows you to tailor configurations to incoming machines. You could -; also use the %u option to tailor it by user name. -; The %m gets replaced with the machine name that is connecting. +;; a service which has a different directory for each machine that connects +;; this allows you to tailor configurations to incoming machines. You could +;; also use the %u option to tailor it by user name. +;; The %m gets replaced with the machine name that is connecting. ;[pchome] ; comment = PC Directories ; path = /usr/pc/%m @@ -205,11 +194,11 @@ ; writable = yes ; ; -; A publicly accessible directory, read/write to all users. Note that all files -; created in the directory by users will be owned by the default user, so -; any user with access can delete any other user's files. Obviously this -; directory must be writable by the default user. Another user could of course -; be specified, in which case all files would be owned by that user instead. +;; A publicly accessible directory, read/write to all users. Note that all files +;; created in the directory by users will be owned by the default user, so +;; any user with access can delete any other user's files. Obviously this +;; directory must be writable by the default user. Another user could of course +;; be specified, in which case all files would be owned by that user instead. ;[public] ; path = /usr/somewhere/else/public ; public = yes @@ -218,11 +207,11 @@ ; printable = no ; ; -; The following two entries demonstrate how to share a directory so that two -; users can place files there that will be owned by the specific users. In this -; setup, the directory should be writable by both users and should have the -; sticky bit set on it to prevent abuse. Obviously this could be extended to -; as many users as required. +;; The following two entries demonstrate how to share a directory so that two +;; users can place files there that will be owned by the specific users. In this +;; setup, the directory should be writable by both users and should have the +;; sticky bit set on it to prevent abuse. Obviously this could be extended to +;; as many users as required. ;[myshare] ; comment = Mary's and Fred's stuff ; path = /usr/somewhere/shared @@ -232,3 +221,4 @@ ; printable = no ; create mask = 0765 + -- cgit From b75580a6bd5a5607f6901915ae0f5357015bd274 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 22:34:28 +0000 Subject: put the new example config file in here as well --- examples/smb.conf.default | 244 ++++++++++++++++++++++------------------------ 1 file changed, 116 insertions(+), 128 deletions(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 9ab5e755ce1..c11594e6fc9 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -1,182 +1,169 @@ -; The global setting for a default install -; Copyright(C) John H Terpstra - 1997 -;======================= Global Settings ===================================== +;; This is the main Samba configuration file. You should read the +;; smb.conf(5) manual page in order to understand the options listed +;; here. Samba has a huge number of configurable options (perhaps too +;; many!) most of which are not shown in this example + +;; Any line which starts with a ; (semi-colon) is a comment and +;; is ignored + + +;;======================= Global Settings ===================================== [global] -; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 - workgroup = WORKGROUP +;; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 + workgroup = MYGROUP -; comment is the equivalent of the NT Description field - comment = Samba Server +;; server string is the equivalent of the NT Description field + server string = Samba Server -; printing = BSD or SYSV or AIX, etc. - printing = bsd +;; This option is important for security. It allows you to restrict +;; connections to machines which are on your local network. The +;; following example restricts access to two C class networks and +;; the "loopback" interface. For more examples of the syntax see +;; the smb.conf man page +; hosts allow = 192.168.1. 192.168.2. 127. + +;; if you want to automatically load your printer list rather +;; than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes -; Uncomment this if you want a guest account, you must add this to /etc/passwd +;; Uncomment this if you want a guest account, you must add this to /etc/passwd +;; otherwise the user "nobody" is used ; guest account = pcguest + +;; this tells Samba to use a separate log file for each machine +;; that connects log file = /usr/local/samba/var/log.%m -; Put a capping on the size of the log files (in Kb) +;; Put a capping on the size of the log files (in Kb). max log size = 50 -; Options for handling file name case sensitivity and / or preservation -; Case Sensitivity breaks many WfW and Win95 apps -; case sensitive = yes - short preserve case = yes - preserve case = yes - -; Security and file integrity related options - lock directory = /usr/local/samba/var/locks - locking = yes -; Strict locking is available for paranoid locking situations only -; enabling this severely degrades read / write performance. -; strict locking = yes -; fake oplocks = yes - share modes = yes - -; Security modes: USER uses Unix username/passwd, SHARE uses WfW type passwords -; SERVER uses an other SMB server (eg: Windows NT Server or Samba) -; to provide authentication services +;; Security mode. Most people will want user level security. See +;; security_level.txt for details. security = user -; Use password server option only with security = server +;; Use password server option only with security = server ; password server = <NT-Server-Name> -; Encrypted Password Support - Off by default. Requires smbpasswd file -; Refer to docs/Encryption.txt - encrypt passwords = no - -; Configuration Options ***** The location of this entry in your smb.conf -; heirachy determines which parameters are overwritten - please watch out! -; Where %m is any SMBName (machine name, or computer name) for which a custom -; configuration is desired +;; Using the following line enables you to customise your configuration +;; on a per machine basis. The %m gets replaced with the netbios name +;; of the machine that is connecting ; include = /usr/local/samba/lib/smb.conf.%m -; Performance Related Options -; Before setting socket options read the smb.conf man page!! +;; Most people will find that this option gives better performance. +;; See speed.txt and the manual pages for details socket options = TCP_NODELAY -; Use keep alive only if really needed!!!! -; keep alive = 60 -; Configure Samba to use multiple interfaces -; Samba will auto-detect network interfaces - only use this if -; the auto-detection does not deliver the needed results -; interfaces = 192.168.12.2/24 176.16.111.22/19 10.11.13.14/255.255.252.0 - -; Browser Control Options: -; Local Master set to True causes Samba to participate in browser elections -; the default setting is true, this causes Samba to behave like a -; Windows NT server. Setting this to false turns off all browser -; election participation. -; local master = yes - -; OS Level gives Samba the power to win browser elections. Windows NT = 32 -; Any value < 32 means NT wins as Master Browser, > 32 Samba gets it -; default = 0, this ensures that Samba will NOT win the browser election. + +;; Configure Samba to use multiple interfaces +;; If you have multiple network interfaces then you must list them +;; here. See the man page for details. +; interfaces = 192.168.12.2/24 192.168.13.2/24 + +;; Browser Control Options: +;; set local master to no if you don't want Samba to become a master +;; browser on your network. Otherwise the normal election rules apply +; local master = no + +;; OS Level determines the precedence of this server in master browser +;; elections. The default value should be reasonable ; os level = 33 -; Domain Master specifies Samba to be the Domain Master Browser -; Only ever set this if there is NO Windows NT Domain Controller on the -; network +;; Domain Master specifies Samba to be the Domain Master Browser. This +;; allows Samba to collate browse lists between subnets. Don't use this +;; if you already have a Windows NT domain controller doing this job ; domain master = yes -; Preferred Master causes Samba to force a local browser election on startup +;; Preferred Master causes Samba to force a local browser election on startup +;; and gives it a slightly higher chance of winning the election ; preferred master = yes -; Use with care only if you have an NT server on your network that has been -; configured at install time to be a primary domain controller. +;; Use only if you have an NT server on your network that has been +;; configured at install time to be a primary domain controller. ; domain controller = <NT-Domain-Controller-SMBName> -; Domain Logon Service Options: -; Domain logon control can be a good thing! See [netlogon] share section below! -; Do NOT set this to yes if there is an Windows NT domain controller -; on the network +;; Enable this if you want Samba to be a domain logon server for +;; Windows95 workstations. ; domain logons = yes -; run a specific logon batch file per workstation (machine) +;; if you enable domain logons then you may want a per-machine or +;; per user logon script +;; run a specific logon batch file per workstation (machine) ; logon script = %m.bat -; run a specific logon batch file per session username (ie: Client User Name) -; logon script = %U.bat +;; run a specific logon batch file per username +; logon script = %u.bat -; Where to store roving profiles (only for Win95 and WinNT) -; %L substitutes for the SMB name we are called, %U is username -; You must uncomment the [Profiles] share below +;; Where to store roving profiles (only for Win95 and WinNT) +;; %L substitutes for this servers netbios name, %U is username +;; You must uncomment the [Profiles] share below ; logon path = \\%L\Profiles\%U -; Windows Internet Name Serving Support Section: -; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server -; the default is NO. If you have an Windows NT Server WINS use it! -; Samba defaults to wins support = no +;; Windows Internet Name Serving Support Section: +;; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server ; wins support = yes -; WINS Server - Tells the NMBD components of Samba to be a WINS Client -; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both +;; WINS Server - Tells the NMBD components of Samba to be a WINS Client +;; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both ; wins server = w.x.y.z -; WINS Proxy - Tells Samba to answer name resolution queries on behalf of a non -; WINS Client capable client, for this to work there must be at least one -; WINS Server on the network. The default is NO. +;; WINS Proxy - Tells Samba to answer name resolution queries on +;; behalf of a non WINS capable client, for this to work there must be +;; at least one WINS Server on the network. The default is NO. ; wins proxy = yes -;============================ Share Definitions ============================== +;;============================ Share Definitions ============================== [homes] comment = Home Directories browseable = no writable = yes -; Un-comment the following and create the netlogon directory for Domain Logons +;; Un-comment the following and create the netlogon directory for Domain Logons ; [netlogon] -; comment = Samba Network Logon Service +; comment = Network Logon Service ; path = /usr/local/samba/lib/netlogon -; Case sensitivity breaks logon script processing!!! -; case sensitive = no ; guest ok = yes -; locking = no ; writable = no -; For browseable say NO if you want to hide the NETLOGON share -; browseable = yes -; share modes = no -; Un-comment the following to provide a specific roving profile share -; the default is to use the user's home directory + +;; Un-comment the following to provide a specific roving profile share +;; the default is to use the user's home directory ;[Profiles] ; path = /usr/local/samba/profiles ; browseable = no -; printable = no ; guest ok = yes -; NOTE: There is NO need to specifically define each individual printer + +;; NOTE: If you have a BSD-style print system there is no need to +;; specifically define each individual printer [printers] comment = All Printers path = /usr/spool/samba browseable = no - printable = yes -; Set public = yes to allow user 'guest account' to print +;; Set public = yes to allow user 'guest account' to print guest ok = no writable = no - create mask = 0700 +;; This one is useful for people to share files ;[tmp] ; comment = Temporary file space ; path = /tmp ; read only = no ; public = yes -; A publicly accessible directory, but read only, except for people in -; the staff group -[public] - comment = Public Stuff - path = /home/samba - public = yes - writable = yes - printable = no - write list = @users +;; A publicly accessible directory, but read only, except for people in +;; the staff group +;[public] +; comment = Public Stuff +; path = /home/samba +; public = yes +; writable = yes +; printable = no +; write list = @users -; Other examples. -; -; A private printer, usable only by fred. Spool data will be placed in fred's -; home directory. Note that fred must have write access to the spool directory, -; wherever it is. +;; Other examples. +;; +;; A private printer, usable only by fred. Spool data will be placed in fred's +;; home directory. Note that fred must have write access to the spool directory, +;; wherever it is. ;[fredsprn] ; comment = Fred's Printer ; valid users = fred @@ -186,8 +173,8 @@ ; writable = no ; printable = yes ; -; A private directory, usable only by fred. Note that fred requires write -; access to the directory. +;; A private directory, usable only by fred. Note that fred requires write +;; access to the directory. ;[fredsdir] ; comment = Fred's Service ; path = /usr/somewhere/private @@ -196,10 +183,10 @@ ; writable = yes ; printable = no ; -; a service which has a different directory for each machine that connects -; this allows you to tailor configurations to incoming machines. You could -; also use the %u option to tailor it by user name. -; The %m gets replaced with the machine name that is connecting. +;; a service which has a different directory for each machine that connects +;; this allows you to tailor configurations to incoming machines. You could +;; also use the %u option to tailor it by user name. +;; The %m gets replaced with the machine name that is connecting. ;[pchome] ; comment = PC Directories ; path = /usr/pc/%m @@ -207,11 +194,11 @@ ; writable = yes ; ; -; A publicly accessible directory, read/write to all users. Note that all files -; created in the directory by users will be owned by the default user, so -; any user with access can delete any other user's files. Obviously this -; directory must be writable by the default user. Another user could of course -; be specified, in which case all files would be owned by that user instead. +;; A publicly accessible directory, read/write to all users. Note that all files +;; created in the directory by users will be owned by the default user, so +;; any user with access can delete any other user's files. Obviously this +;; directory must be writable by the default user. Another user could of course +;; be specified, in which case all files would be owned by that user instead. ;[public] ; path = /usr/somewhere/else/public ; public = yes @@ -220,11 +207,11 @@ ; printable = no ; ; -; The following two entries demonstrate how to share a directory so that two -; users can place files there that will be owned by the specific users. In this -; setup, the directory should be writable by both users and should have the -; sticky bit set on it to prevent abuse. Obviously this could be extended to -; as many users as required. +;; The following two entries demonstrate how to share a directory so that two +;; users can place files there that will be owned by the specific users. In this +;; setup, the directory should be writable by both users and should have the +;; sticky bit set on it to prevent abuse. Obviously this could be extended to +;; as many users as required. ;[myshare] ; comment = Mary's and Fred's stuff ; path = /usr/somewhere/shared @@ -234,3 +221,4 @@ ; printable = no ; create mask = 0765 + -- cgit From 92e7092af1daf9349ca9fb00cd27c0ddc21b37d9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 22:40:45 +0000 Subject: add a note about running testparm after modifying smb.conf --- examples/smb.conf.default | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index c11594e6fc9..2a0e3d3c833 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -6,6 +6,8 @@ ;; Any line which starts with a ; (semi-colon) is a comment and ;; is ignored +;; Whenever you modify this file you should run the command "testparm" +;; to check that you have not many any basic syntactic errors. ;;======================= Global Settings ===================================== [global] @@ -141,6 +143,7 @@ ;; Set public = yes to allow user 'guest account' to print guest ok = no writable = no + printable = yes ;; This one is useful for people to share files ;[tmp] -- cgit From 6395e2efaee8d22a83d498c14ba8145456212d99 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Fri, 17 Oct 1997 22:41:19 +0000 Subject: add a note about running testparm after modifying smb.conf --- examples/smb.conf.default | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index c11594e6fc9..2a0e3d3c833 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -6,6 +6,8 @@ ;; Any line which starts with a ; (semi-colon) is a comment and ;; is ignored +;; Whenever you modify this file you should run the command "testparm" +;; to check that you have not many any basic syntactic errors. ;;======================= Global Settings ===================================== [global] @@ -141,6 +143,7 @@ ;; Set public = yes to allow user 'guest account' to print guest ok = no writable = no + printable = yes ;; This one is useful for people to share files ;[tmp] -- cgit From 6904c2de080b2a9702800e9e4126386ced20569d Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Fri, 17 Oct 1997 23:08:07 +0000 Subject: .cvsignore: Added make_smbcodepage interface.c: Added is_local_net(). locking.c: Added Fix for zero length share files from Gerald Werner <wernerg@mfldclin.edu> plus a race condition fix for the fix. nameannounce.c: Made function static. namedbresp.c: extern int ClientDGRAM removed - not used. namedbserver.c: extern int ClientDGRAM removed - not used. namedbsubnet.c: Added code to make sockets per subnet. namepacket.c: Added code to read from all sockets & filter. nameresp.c: extern int ClientDGRAM removed - not used. nameserv.c: Indentation tidyup :-). nameserv.h: Added sockets to struct subnet. nameservresp.c: Improved debug message. nmbd.c: Changed to terminte on listen_for_packets exiting. nmbsync.c: extern int ClientDGRAM & ClientNMB removed - not used. proto.h: The usual. util.c: Fixed debug message. Jeremy (jallison@whistle.com) --- source/.cvsignore | 1 + source/include/nameserv.h | 2 + source/include/proto.h | 17 ++-- source/lib/interface.c | 12 +++ source/lib/util.c | 4 +- source/locking/locking.c | 75 ++++++++++----- source/nameannounce.c | 166 ++++++++++++++++---------------- source/namedbresp.c | 1 - source/namedbserver.c | 1 - source/namedbsubnet.c | 67 +++++++++++-- source/namepacket.c | 238 +++++++++++++++++++++++++++++++++++----------- source/nameresp.c | 1 - source/nameserv.c | 70 +++++++------- source/nameservresp.c | 3 +- source/nmbd/nmbd.c | 29 ++++-- source/nmbsync.c | 3 - 16 files changed, 454 insertions(+), 236 deletions(-) diff --git a/source/.cvsignore b/source/.cvsignore index 9b7ea034be9..f6b77ee2f96 100644 --- a/source/.cvsignore +++ b/source/.cvsignore @@ -1,6 +1,7 @@ Makefile.RPM makefile makefile.sunos5 +make_smbcodepage nmbd nmblookup smbclient diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 81487e9ce9a..ecd19b95634 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -291,6 +291,8 @@ struct subnet_record struct in_addr bcast_ip; struct in_addr mask_ip; struct in_addr myip; + int nmb_sock; /* socket to listen for unicast 137. */ + int dgram_sock; /* socket to listen for unicast 138. */ }; /* a resource record */ diff --git a/source/include/proto.h b/source/include/proto.h index 85ef0943400..fa689d1c90f 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -93,9 +93,9 @@ void CloseDir(void *p); char *ReadDirName(void *p); BOOL SeekDir(void *p,int pos); int TellDir(void *p); -void DirCacheAdd(char *path,char *name,char *dname,int snum); -char *DirCacheCheck(char *path,char *name,int snum); -void DirCacheFlush(int snum); +void DirCacheAdd( char *path, char *name, char *dname, int snum ); +char *DirCacheCheck( char *path, char *name, int snum ); +void DirCacheFlush( int snum ); /*The following definitions come from fault.c */ @@ -111,6 +111,7 @@ void load_interfaces(void); void iface_set_default(char *ip,char *bcast,char *nmask); BOOL ismyip(struct in_addr ip); BOOL ismybcast(struct in_addr bcast); +BOOL is_local_net(struct in_addr from); int iface_count(void); struct in_addr *iface_n_ip(int n); struct in_addr *iface_bcast(struct in_addr ip); @@ -372,11 +373,6 @@ void sync_server(enum state_type state, char *serv_name, char *work_name, int name_type, struct subnet_record *d, struct in_addr ip); -void do_announce_host(int command, - char *from_name, int from_type, struct in_addr from_ip, - char *to_name , int to_type , struct in_addr to_ip, - time_t announce_interval, - char *server_name, int server_type, char *server_comment); void announce_my_servers_removed(void); void announce_server(struct subnet_record *d, struct work_record *work, char *name, char *comment, time_t ttl, int server_type); @@ -503,7 +499,7 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, char *data,int len); void queue_packet(struct packet_struct *packet); void run_packet_queue(); -void listen_for_packets(BOOL run_election); +BOOL listen_for_packets(BOOL run_election); BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname, char *dstname,int src_type,int dest_type, struct in_addr dest_ip,struct in_addr src_ip); @@ -946,6 +942,9 @@ int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize); int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize); int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize); +/*The following definitions come from ubi_dLinkList.c */ + + /*The following definitions come from ufc.c */ char *ufc_crypt(char *key,char *salt); diff --git a/source/lib/interface.c b/source/lib/interface.c index 1dc605ff2fd..c920cc0cfcf 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -399,6 +399,18 @@ BOOL ismybcast(struct in_addr bcast) return False; } +/**************************************************************************** + check if a packet is from a local (known) net + **************************************************************************/ +BOOL is_local_net(struct in_addr from) +{ + struct interface *i; + for (i=local_interfaces;i;i=i->next) + if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr)) + return True; + return False; +} + /**************************************************************************** how many interfaces do we have **************************************************************************/ diff --git a/source/lib/util.c b/source/lib/util.c index a82713a0d84..b69b30d20cd 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3284,8 +3284,8 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) { if (port) { if (port == SMB_PORT || port == NMB_PORT) - DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n", - port,socket_addr,strerror(errno))); + DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n", + port,inet_ntoa(sock.sin_addr),strerror(errno))); close(res); if (dlevel > 0 && port < 1000) diff --git a/source/locking/locking.c b/source/locking/locking.c index 5071121bed0..bbc0c0033ff 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -715,6 +715,31 @@ static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) return(True); } +/******************************************************************* +Force a share file to be deleted. +********************************************************************/ + +static int delete_share_file( int cnum, char *fname ) +{ + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + + if(unlink(fname) != 0) + { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + /* return to our previous privilage level */ + unbecome_root(False); + + return 0; +} + /******************************************************************* lock a share mode file. ******************************************************************/ @@ -820,6 +845,31 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok { int fd = (int)token; int ret = True; + struct stat sb; + pstring fname; + + /* Fix for zero length share files from + Gerald Werner <wernerg@mfldclin.edu> */ + + share_name(cnum, dev, inode, fname); + + /* get the share mode file size */ + if(fstat((int)token, &sb) != 0) + { + DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + sb.st_size = 1; + ret = False; + } + + /* If the file was zero length, we must delete before + doing the unlock to avoid a race condition (see + the code in lock_share_mode_entry for details. + */ + + /* remove the share file if zero length */ + if(sb.st_size == 0) + delete_share_file(cnum, fname); /* token is the fd of the open share mode file. */ /* Unlock the first byte. */ @@ -834,31 +884,6 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok return ret; } -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ - -static int delete_share_file( int cnum, char *fname ) -{ - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilage level */ - unbecome_root(False); - - return 0; -} - /******************************************************************* Read a share file into a buffer. ********************************************************************/ diff --git a/source/nameannounce.c b/source/nameannounce.c index d69ee32ddf7..b8dcb71fffd 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -67,7 +67,7 @@ void announce_request(struct work_record *work, struct in_addr ip) work->needannounce = True; DEBUG(2,("sending announce request to %s for workgroup %s\n", - inet_ntoa(ip),work->work_group)); + inet_ntoa(ip),work->work_group)); bzero(outbuf,sizeof(outbuf)); p = outbuf; @@ -84,9 +84,9 @@ void announce_request(struct work_record *work, struct in_addr ip) of 0x1e, then we could get the master browser to announce to us instead of the members of the workgroup. wha-hey! */ - send_mailslot_reply(False, BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip)); + send_mailslot_reply(False, BROWSE_MAILSLOT, ClientDGRAM, + outbuf,PTR_DIFF(p,outbuf), + myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip)); } @@ -106,15 +106,15 @@ void do_announce_request(char *info, char *to_name, int announce_type, p++; DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n", - announce_type, info, inet_ntoa(dest_ip),to_name,to)); + announce_type, info, inet_ntoa(dest_ip),to_name,to)); StrnCpy(p,info,16); strupper(p); p = skip_string(p,1); - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,to_name,from,to,dest_ip,*iface_ip(dest_ip)); + send_mailslot_reply(False,BROWSE_MAILSLOT, ClientDGRAM, + outbuf,PTR_DIFF(p,outbuf), + myname,to_name,from,to,dest_ip,*iface_ip(dest_ip)); } @@ -144,48 +144,48 @@ void sync_server(enum state_type state, char *serv_name, char *work_name, /**************************************************************************** send a host announcement packet **************************************************************************/ -void do_announce_host(int command, +static void do_announce_host(int command, char *from_name, int from_type, struct in_addr from_ip, 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; + pstring outbuf; + char *p; - bzero(outbuf,sizeof(outbuf)); - p = outbuf+1; + bzero(outbuf,sizeof(outbuf)); + p = outbuf+1; - /* command type */ - CVAL(outbuf,0) = command; + /* command type */ + CVAL(outbuf,0) = command; - /* announcement parameters */ - CVAL(p,0) = updatecount; - SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ + /* announcement parameters */ + CVAL(p,0) = updatecount; + SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ - StrnCpy(p+5,server_name,16); - strupper(p+5); + StrnCpy(p+5,server_name,16); + strupper(p+5); - CVAL(p,21) = lp_major_announce_version(); /* major version */ - CVAL(p,22) = lp_minor_announce_version(); /* minor version */ + CVAL(p,21) = lp_major_announce_version(); /* major version */ + CVAL(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 */ + 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 */ - pstrcpy(p+31,server_comment); - p += 31; - p = skip_string(p,1); + pstrcpy(p+31,server_comment); + p += 31; + p = skip_string(p,1); - debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); - /* send the announcement */ - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - from_name, to_name, - from_type, to_type, - to_ip, from_ip); + /* send the announcement */ + send_mailslot_reply(False,BROWSE_MAILSLOT, ClientDGRAM, outbuf, + PTR_DIFF(p,outbuf), + from_name, to_name, + from_type, to_type, + to_ip, from_ip); } @@ -217,58 +217,58 @@ void announce_my_servers_removed(void) void announce_server(struct subnet_record *d, struct work_record *work, char *name, char *comment, time_t ttl, int server_type) { - /* domain type cannot have anything in it that might confuse - a client into thinking that the domain is in fact a server. - (SV_TYPE_SERVER_UNIX, for example) - */ - uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; - BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip); - - if(wins_iface) - { - DEBUG(0,("announce_server: error - announcement requested on WINS \ + /* domain type cannot have anything in it that might confuse + a client into thinking that the domain is in fact a server. + (SV_TYPE_SERVER_UNIX, for example) + */ + uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; + BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip); + + if(wins_iface) + { + DEBUG(0,("announce_server: error - announcement requested on WINS \ interface for workgroup %s, name %s\n", work->work_group, name)); - return; - } + return; + } - /* Only do domain announcements if we are a master and it's - our name we're being asked to announce. */ - if (AM_MASTER(work) && strequal(myname,name)) - { - DEBUG(3,("sending local master announce to %s for %s(1e)\n", - inet_ntoa(d->bcast_ip),work->work_group)); + /* Only do domain announcements if we are a master and it's + our name we're being asked to announce. */ + if (AM_MASTER(work) && strequal(myname,name)) + { + DEBUG(3,("sending local master announce to %s for %s(1e)\n", + inet_ntoa(d->bcast_ip),work->work_group)); - do_announce_host(ANN_LocalMasterAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1e, d->bcast_ip, - ttl, - name, server_type, comment); + do_announce_host(ANN_LocalMasterAnnouncement, + name , 0x00, d->myip, + work->work_group, 0x1e, d->bcast_ip, + ttl, + name, server_type, comment); - DEBUG(3,("sending domain announce to %s for %s\n", - inet_ntoa(d->bcast_ip),work->work_group)); + DEBUG(3,("sending domain announce to %s for %s\n", + inet_ntoa(d->bcast_ip),work->work_group)); - /* XXXX should we do a domain-announce-kill? */ - if (server_type != 0) - { - do_announce_host(ANN_DomainAnnouncement, - name , 0x00, d->myip, - MSBROWSE, 0x01, d->bcast_ip, - ttl, - work->work_group, server_type ? domain_type : 0, - name); - } - } - else - { - DEBUG(3,("sending host announce to %s for %s(1d)\n", - inet_ntoa(d->bcast_ip),work->work_group)); - - do_announce_host(ANN_HostAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1d, d->bcast_ip, - ttl, - name, server_type, comment); - } + /* XXXX should we do a domain-announce-kill? */ + if (server_type != 0) + { + do_announce_host(ANN_DomainAnnouncement, + name , 0x00, d->myip, + MSBROWSE, 0x01, d->bcast_ip, + ttl, + work->work_group, server_type ? domain_type : 0, + name); + } + } + else + { + DEBUG(3,("sending host announce to %s for %s(1d)\n", + inet_ntoa(d->bcast_ip),work->work_group)); + + do_announce_host(ANN_HostAnnouncement, + name , 0x00, d->myip, + work->work_group, 0x1d, d->bcast_ip, + ttl, + name, server_type, comment); + } } /**************************************************************************** diff --git a/source/namedbresp.c b/source/namedbresp.c index c8a31a6c79b..e9fe39c3d73 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -25,7 +25,6 @@ #include "includes.h" extern int ClientNMB; -extern int ClientDGRAM; extern struct subnet_record *subnetlist; diff --git a/source/namedbserver.c b/source/namedbserver.c index 9223cb6ce6a..7440b42494a 100644 --- a/source/namedbserver.c +++ b/source/namedbserver.c @@ -32,7 +32,6 @@ #include "smb.h" extern int ClientNMB; -extern int ClientDGRAM; extern int DEBUGLEVEL; diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c index c6663d71fd4..3597c323875 100644 --- a/source/namedbsubnet.c +++ b/source/namedbsubnet.c @@ -33,6 +33,7 @@ extern int ClientNMB; extern int ClientDGRAM; +extern int global_nmb_port; extern int DEBUGLEVEL; @@ -130,14 +131,60 @@ struct subnet_record *find_subnet_all(struct in_addr bcast_ip) } /**************************************************************************** - create a domain entry + create a subnet entry ****************************************************************************/ -static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip, BOOL add) +static struct subnet_record *make_subnet(struct in_addr myip, struct in_addr bcast_ip, + struct in_addr mask_ip, BOOL add) { - struct subnet_record *d; + struct subnet_record *d = NULL; + int nmb_sock, dgram_sock; + + /* Check if we are creating the WINS subnet - if so don't create + sockets, use the ClientNMB and ClientDGRAM sockets instead. + */ + + if(ip_equal(bcast_ip, wins_ip)) + { + 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)) == -1) + { + DEBUG(0,("make_subnet: Failed to open nmb socket on interface %s \ +for port %d. Error was %s\n", inet_ntoa(myip), global_nmb_port, strerror(errno))); + return NULL; + } + + if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1) + { + DEBUG(0,("make_subnet: Failed to open dgram socket on interface %s \ +for port %d. Error was %s\n", inet_ntoa(myip), DGRAM_PORT, 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"); + + } + d = (struct subnet_record *)malloc(sizeof(*d)); - if (!d) return(NULL); + if (!d) + { + DEBUG(0,("make_subnet: malloc fail !\n")); + close(nmb_sock); + close(dgram_sock); + return(NULL); + } bzero((char *)d,sizeof(*d)); @@ -146,6 +193,9 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr d->bcast_ip = bcast_ip; d->mask_ip = mask_ip; + d->myip = myip; + d->nmb_sock = nmb_sock; + d->dgram_sock = dgram_sock; d->workgrouplist = NULL; if(add) @@ -158,7 +208,8 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr add a domain entry. creates a workgroup, if necessary, and adds the domain to the named a workgroup. ****************************************************************************/ -static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, +static struct subnet_record *add_subnet_entry(struct in_addr myip, + struct in_addr bcast_ip, struct in_addr mask_ip, char *name, BOOL create_subnets, BOOL add) { @@ -175,7 +226,7 @@ static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, if(create_subnets == True) { /* Create new subnets. */ - if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL) + if((d = make_subnet(myip, bcast_ip, mask_ip, add)) == NULL) { DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n", inet_ntoa(bcast_ip) )); @@ -265,7 +316,7 @@ void add_my_subnets(char *group) */ for (i = local_interfaces; i; i = i->next) { - add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True); + add_subnet_entry(i->ip, i->bcast,i->nmask,group, create_subnets, True); } /* If we are using WINS, then we must add the workgroup to the WINS @@ -278,7 +329,7 @@ void add_my_subnets(char *group) if (lp_wins_support() || lp_wins_server()) { struct in_addr wins_nmask = ipzero; - wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False); + wins_subnet = add_subnet_entry(ipzero, wins_ip, wins_nmask, group, create_subnets, False); } /* Ensure we only create the subnets once. */ diff --git a/source/namepacket.c b/source/namepacket.c index 4a9f586a762..55c850f2544 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -503,72 +503,198 @@ void run_packet_queue() } } +/**************************************************************************** + 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 *d = 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 (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) + 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 (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) + { + FD_SET(d->nmb_sock,pset); + sock_array[num++] = d->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 (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) + { + FD_SET(d->dgram_sock,pset); + sock_array[num++] = d->dgram_sock; + } + + *listen_number = (count*2) + 2; + *ppset = pset; + *psock_array = sock_array; + + return False; +} + /**************************************************************************** listens for NMB or DGRAM packets, and queues them ***************************************************************************/ -void listen_for_packets(BOOL run_election) +BOOL listen_for_packets(BOOL run_election) { - fd_set fds; - int selrtn; - struct timeval timeout; + static fd_set *listen_set = NULL; + static int listen_number = 0; + static int *sock_array = NULL; - FD_ZERO(&fds); - FD_SET(ClientNMB,&fds); - FD_SET(ClientDGRAM,&fds); + fd_set fds; + int selrtn; + struct timeval timeout; - /* during elections and when expecting a netbios response packet we - need to send election packets at tighter intervals + if(listen_set == NULL) + { + 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; + } + } - ideally it needs to be the interval (in ms) between time now and - the time we are expecting the next netbios packet */ + memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); - timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP; - timeout.tv_usec = 0; + /* during elections and when expecting a netbios response packet we + need to send election packets at tighter intervals - /* We can only take term signals when we are in the select. */ - BlockSignals(False, SIGTERM); - selrtn = sys_select(&fds,&timeout); - BlockSignals(True, SIGTERM); + ideally it needs to be the interval (in ms) between time now and + the time we are expecting the next netbios packet */ - if (FD_ISSET(ClientNMB,&fds)) - { - struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); - if (packet) - { - if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && - packet->port == NMB_PORT) - { - DEBUG(7,("discarding own packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } - else - { - queue_packet(packet); - } - } - } + timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP; + timeout.tv_usec = 0; - if (FD_ISSET(ClientDGRAM,&fds)) - { - struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); - if (packet) - { - if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && - packet->port == DGRAM_PORT) - { - DEBUG(7,("discarding own packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } - else - { - queue_packet(packet); - } - } - } + /* We can only take term signals when we are in the select. */ + BlockSignals(False, SIGTERM); + selrtn = sys_select(&fds,&timeout); + BlockSignals(True, SIGTERM); + + if(selrtn > 0) + { + int i; + + 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 check it + * came from one of our local nets. We should only be + * receiving broadcasts from nets we have subnets for. + * + * Note that this filter precludes remote announces. + * If we need this to work we will have to add an + * 'allow local announce' parameter that gives a + * list of networks we will allow through the filter. + */ + if((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 == NMB_PORT) + { + DEBUG(7,("discarding own packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } + else + { + 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 check it + * came from one of our local nets. We should only be + * receiving broadcasts from nets we have subnets for. + * + * Note that this filter precludes remote announces. + * If we need this to work we will have to add an + * 'allow local announce' parameter that gives a + * list of networks we will allow through the filter. + */ + if((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 packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } + else + { + queue_packet(packet); + } + } + } + } /* end processing 138 socket. */ + } /* end for */ + } /* end if selret > 0 */ + return False; } @@ -636,7 +762,7 @@ BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,ch p.ip = dest_ip; p.port = DGRAM_PORT; - p.fd = ClientDGRAM; + p.fd = fd; p.timestamp = time(NULL); p.packet_type = DGRAM_PACKET; diff --git a/source/nameresp.c b/source/nameresp.c index 2e625735c49..81624fcaf1b 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -25,7 +25,6 @@ #include "includes.h" extern int ClientNMB; -extern int ClientDGRAM; extern struct subnet_record *subnetlist; diff --git a/source/nameserv.c b/source/nameserv.c index bc37d1c424e..a90b41f834c 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -168,7 +168,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) } else { - /* broadcast the packet, but it comes from ipzero */ + /* broadcast the packet */ queue_netbios_packet(d,ClientNMB, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, name, type, nb_flags, GET_TTL(0),0,NULL,NULL, @@ -214,45 +214,43 @@ void add_domain_logon_names(void) ****************************************************************************/ void add_domain_master_bcast(void) { - struct subnet_record *d; - - if (!lp_domain_master()) return; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work = find_workgroupstruct(d, myworkgroup, True); - - if (work && work->dom_state == DOMAIN_NONE) - { - struct nmb_name n; - make_nmb_name(&n,myworkgroup,0x1b,scope); + struct subnet_record *d; - if (!find_name(d->namelist, &n, FIND_SELF)) - { - DEBUG(0,("%s add_domain_names: attempting to become domain \ -master browser on workgroup %s %s\n", - timestring(), myworkgroup, inet_ntoa(d->bcast_ip))); + if (!lp_domain_master()) return; - /* send out a query to establish whether there's a - domain controller on the local subnet. if not, - we can become a domain controller. it's only - polite that we check, before claiming the - NetBIOS name 0x1b. - */ + for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) + { + struct work_record *work = find_workgroupstruct(d, myworkgroup, True); - DEBUG(0,("add_domain_names:querying subnet %s \ -for domain master on workgroup %s\n", - inet_ntoa(d->bcast_ip), myworkgroup)); + if (work && work->dom_state == DOMAIN_NONE) + { + struct nmb_name n; + make_nmb_name(&n,myworkgroup,0x1b,scope); - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - NAME_QUERY_DOMAIN, - myworkgroup, 0x1b, - 0, 0,0,NULL,NULL, - True, False, - d->bcast_ip, d->bcast_ip, 0); - } - } - } + if (!find_name(d->namelist, &n, FIND_SELF)) + { + DEBUG(0,("%s add_domain_names: attempting to become domain \ +master browser on workgroup %s %s\n", timestring(), myworkgroup, inet_ntoa(d->bcast_ip))); + + /* send out a query to establish whether there's a + domain controller on the local subnet. if not, + we can become a domain controller. it's only + polite that we check, before claiming the + NetBIOS name 0x1b. + */ + + DEBUG(0,("add_domain_names:querying subnet %s \ +for domain master on workgroup %s\n", inet_ntoa(d->bcast_ip), myworkgroup)); + + queue_netbios_packet(d,ClientNMB,NMB_QUERY, + NAME_QUERY_DOMAIN, + myworkgroup, 0x1b, + 0, 0,0,NULL,NULL, + True, False, + d->bcast_ip, d->bcast_ip, 0); + } + } + } } diff --git a/source/nameservresp.c b/source/nameservresp.c index deb56c0850e..61e4a835f46 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -806,7 +806,8 @@ void response_netbios_packet(struct packet_struct *p) struct subnet_record *d = NULL; if (!(n = find_response_record(&d,nmb->header.name_trn_id))) { - DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n")); + DEBUG(2,("unknown netbios response id %d (received late or from nmblookup?)\n", + nmb->header.name_trn_id)); return; } diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index c7af54fa13b..047284832f0 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -34,8 +34,9 @@ pstring servicesf = CONFIGFILE; extern pstring scope; -int ClientNMB = -1; -int ClientDGRAM = -1; +int ClientNMB = -1; +int ClientDGRAM = -1; +int global_nmb_port = -1; extern pstring myhostname; static pstring host_file; @@ -302,7 +303,8 @@ static void process(void) { time_t t = time(NULL); run_election = check_elections(); - listen_for_packets(run_election); + if(listen_for_packets(run_election)) + return; run_packet_queue(); run_elections(t); @@ -338,12 +340,19 @@ static BOOL open_sockets(BOOL isdaemon, int port) return False; } + /* 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,interpret_addr(lp_socket_address())); + ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0); else ClientNMB = 0; - ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address())); + ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0); if (ClientNMB == -1) return(False); @@ -353,7 +362,7 @@ static BOOL open_sockets(BOOL isdaemon, int port) set_socket_options(ClientNMB,"SO_BROADCAST"); set_socket_options(ClientDGRAM,"SO_BROADCAST"); - DEBUG(3,("Sockets opened.\n")); + DEBUG(3,("open_sockets: Broadcast sockets opened.\n")); return True; } @@ -460,12 +469,12 @@ static void usage(char *pname) **************************************************************************/ int main(int argc,char *argv[]) { - int port = NMB_PORT; int opt; extern FILE *dbf; extern char *optarg; char pidFile[100] = { 0 }; + global_nmb_port = NMB_PORT; *host_file = 0; StartupTime = time(NULL); @@ -537,7 +546,7 @@ static void usage(char *pname) DEBUGLEVEL = atoi(optarg); break; case 'p': - port = atoi(optarg); + global_nmb_port = atoi(optarg); break; case 'h': usage(argv[0]); @@ -618,9 +627,9 @@ static void usage(char *pname) } - DEBUG(3,("Opening sockets %d\n", port)); + DEBUG(3,("Opening sockets %d\n", global_nmb_port)); - if (!open_sockets(is_daemon,port)) return 1; + if (!open_sockets(is_daemon,global_nmb_port)) return 1; load_interfaces(); add_my_subnets(myworkgroup); diff --git a/source/nmbsync.c b/source/nmbsync.c index de2f7aa00f1..34d309d0032 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -24,9 +24,6 @@ #define REPLACE_GETPASS #include "includes.h" -extern int ClientNMB; -extern int ClientDGRAM; - extern int DEBUGLEVEL; extern pstring myname; -- cgit From db9aad07481f48c0fe2108d4ab0b2bc9b632816c Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Sat, 18 Oct 1997 00:22:04 +0000 Subject: After talking with Andrew added "interfaces only" parameter that turns off the filtering on the broadcast socket by default. Jeremy (jallison@whistle.com) --- source/include/proto.h | 1 + source/namepacket.c | 27 ++++++++------------------- source/param/loadparm.c | 4 ++++ 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index fa689d1c90f..e0ddee89439 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -185,6 +185,7 @@ BOOL lp_browse_list(void); BOOL lp_unix_realname(void); BOOL lp_nis_home_map(void); BOOL lp_time_server(void); +BOOL lp_interfaces_only(void); int lp_os_level(void); int lp_max_ttl(void); int lp_max_log_size(void); diff --git a/source/namepacket.c b/source/namepacket.c index 55c850f2544..ba1c4044a3b 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -622,18 +622,12 @@ BOOL listen_for_packets(BOOL run_election) struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); if (packet) { - /* - * If we got a packet on the broadcast socket check it - * came from one of our local nets. We should only be - * receiving broadcasts from nets we have subnets for. - * - * Note that this filter precludes remote announces. - * If we need this to work we will have to add an - * 'allow local announce' parameter that gives a - * list of networks we will allow through the filter. + * 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((sock_array[i] == ClientNMB) && (!is_local_net(packet->ip))) + if(lp_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)); @@ -663,16 +657,11 @@ BOOL listen_for_packets(BOOL run_election) if (packet) { /* - * If we got a packet on the broadcast socket check it - * came from one of our local nets. We should only be - * receiving broadcasts from nets we have subnets for. - * - * Note that this filter precludes remote announces. - * If we need this to work we will have to add an - * 'allow local announce' parameter that gives a - * list of networks we will allow through the filter. + * 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((sock_array[i] == ClientDGRAM) && (!is_local_net(packet->ip))) + if(lp_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)); diff --git a/source/param/loadparm.c b/source/param/loadparm.c index b8776500781..1568e3abf51 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -183,6 +183,7 @@ typedef struct BOOL bUnixRealname; BOOL bNISHomeMap; BOOL bTimeServer; + BOOL bInterfacesOnly; } global; static global Globals; @@ -410,6 +411,7 @@ struct parm_struct {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL}, {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL}, {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL}, + {"interfaces only", P_BOOL, P_GLOBAL, &Globals.bInterfacesOnly, NULL}, {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL}, {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL}, {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL}, @@ -655,6 +657,7 @@ static void init_globals(void) coding_system = interpret_coding_system (KANJI, SJIS_CODE); Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE; Globals.bTimeServer = False; + Globals.bInterfacesOnly = False; /* these parameters are set to defaults that are more appropriate for the increasing samba install base: @@ -867,6 +870,7 @@ FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList) FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname) FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap) FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer) +FN_GLOBAL_BOOL(lp_interfaces_only,&Globals.bInterfacesOnly) FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) -- cgit From 1b2d1fb9b18340505f57cac320efa95aa93a4c7b Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Sat, 18 Oct 1997 05:27:20 +0000 Subject: Fixed small typo. --- examples/smb.conf.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 2a0e3d3c833..0d2c6234c70 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -153,7 +153,7 @@ ; public = yes ;; A publicly accessible directory, but read only, except for people in -;; the staff group +;; the users group ;[public] ; comment = Public Stuff ; path = /home/samba -- cgit From 2b15116a9ab48381445a6b7fb4352f71bf8860c0 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Sat, 18 Oct 1997 05:28:34 +0000 Subject: Fixed small typo. --- examples/smb.conf.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 2a0e3d3c833..0d2c6234c70 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -153,7 +153,7 @@ ; public = yes ;; A publicly accessible directory, but read only, except for people in -;; the staff group +;; the users group ;[public] ; comment = Public Stuff ; path = /home/samba -- cgit From ce54f3a7a965b0a9f888dc45d6f4633609d5ca08 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sat, 18 Oct 1997 15:01:01 +0000 Subject: put the NT_STATUS_ALLOTTED_SPACE_EXCEEDED error in instead of 0x99. whatever that means. --- source/smbd/reply.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 56288df0739..c5b7c500719 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -26,6 +26,7 @@ #include "includes.h" #include "trans2.h" +#include "nterr.h" /* look in server.c for some explanation of these variables */ extern int Protocol; @@ -498,7 +499,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Rejecting workstation trust account %s",user)); SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(0x99,0xc000)); /* 0x99 NT error, 0xc00 */ + return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */ } computer_id = True; #else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ -- cgit From cdf4aa565302df07b0232c52506ab77be968f80d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 19 Oct 1997 05:16:54 +0000 Subject: add a section on encryption and change the formatting a bit --- examples/smb.conf.default | 211 ++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 103 deletions(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 0d2c6234c70..9664ac1ab47 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -1,124 +1,131 @@ -;; This is the main Samba configuration file. You should read the -;; smb.conf(5) manual page in order to understand the options listed -;; here. Samba has a huge number of configurable options (perhaps too -;; many!) most of which are not shown in this example - -;; Any line which starts with a ; (semi-colon) is a comment and -;; is ignored - -;; Whenever you modify this file you should run the command "testparm" -;; to check that you have not many any basic syntactic errors. - -;;======================= Global Settings ===================================== +# This is the main Samba configuration file. You should read the +# smb.conf(5) manual page in order to understand the options listed +# here. Samba has a huge number of configurable options (perhaps too +# many!) most of which are not shown in this example +# +# Any line which starts with a ; (semi-colon) or a # (hash) +# is a comment and is ignored. In this example we will use a # +# for commentry and a ; for parts of the config file that you +# may wish to enable +# +# NOTE: Whenever you modify this file you should run the command "testparm" +# to check that you have not many any basic syntactic errors. +# +#======================= Global Settings ===================================== [global] -;; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 +# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 workgroup = MYGROUP -;; server string is the equivalent of the NT Description field +# server string is the equivalent of the NT Description field server string = Samba Server -;; This option is important for security. It allows you to restrict -;; connections to machines which are on your local network. The -;; following example restricts access to two C class networks and -;; the "loopback" interface. For more examples of the syntax see -;; the smb.conf man page +# This option is important for security. It allows you to restrict +# connections to machines which are on your local network. The +# following example restricts access to two C class networks and +# the "loopback" interface. For more examples of the syntax see +# the smb.conf man page ; hosts allow = 192.168.1. 192.168.2. 127. -;; if you want to automatically load your printer list rather -;; than setting them up individually then you'll need this +# if you want to automatically load your printer list rather +# than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes -;; Uncomment this if you want a guest account, you must add this to /etc/passwd -;; otherwise the user "nobody" is used +# Uncomment this if you want a guest account, you must add this to /etc/passwd +# otherwise the user "nobody" is used ; guest account = pcguest -;; this tells Samba to use a separate log file for each machine -;; that connects +# this tells Samba to use a separate log file for each machine +# that connects log file = /usr/local/samba/var/log.%m -;; Put a capping on the size of the log files (in Kb). +# Put a capping on the size of the log files (in Kb). max log size = 50 -;; Security mode. Most people will want user level security. See -;; security_level.txt for details. +# Security mode. Most people will want user level security. See +# security_level.txt for details. security = user -;; Use password server option only with security = server +# Use password server option only with security = server ; password server = <NT-Server-Name> -;; Using the following line enables you to customise your configuration -;; on a per machine basis. The %m gets replaced with the netbios name -;; of the machine that is connecting +# You may wish to use password encryption. Please read +# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation. +# Do not enable this option unless you have read those documents +; encrypt passwords = yes + +# Using the following line enables you to customise your configuration +# on a per machine basis. The %m gets replaced with the netbios name +# of the machine that is connecting ; include = /usr/local/samba/lib/smb.conf.%m -;; Most people will find that this option gives better performance. -;; See speed.txt and the manual pages for details +# Most people will find that this option gives better performance. +# See speed.txt and the manual pages for details socket options = TCP_NODELAY -;; Configure Samba to use multiple interfaces -;; If you have multiple network interfaces then you must list them -;; here. See the man page for details. +# Configure Samba to use multiple interfaces +# If you have multiple network interfaces then you must list them +# here. See the man page for details. ; interfaces = 192.168.12.2/24 192.168.13.2/24 -;; Browser Control Options: -;; set local master to no if you don't want Samba to become a master -;; browser on your network. Otherwise the normal election rules apply +# Browser Control Options: +# set local master to no if you don't want Samba to become a master +# browser on your network. Otherwise the normal election rules apply ; local master = no -;; OS Level determines the precedence of this server in master browser -;; elections. The default value should be reasonable +# OS Level determines the precedence of this server in master browser +# elections. The default value should be reasonable ; os level = 33 -;; Domain Master specifies Samba to be the Domain Master Browser. This -;; allows Samba to collate browse lists between subnets. Don't use this -;; if you already have a Windows NT domain controller doing this job +# Domain Master specifies Samba to be the Domain Master Browser. This +# allows Samba to collate browse lists between subnets. Don't use this +# if you already have a Windows NT domain controller doing this job ; domain master = yes -;; Preferred Master causes Samba to force a local browser election on startup -;; and gives it a slightly higher chance of winning the election +# Preferred Master causes Samba to force a local browser election on startup +# and gives it a slightly higher chance of winning the election ; preferred master = yes -;; Use only if you have an NT server on your network that has been -;; configured at install time to be a primary domain controller. +# Use only if you have an NT server on your network that has been +# configured at install time to be a primary domain controller. ; domain controller = <NT-Domain-Controller-SMBName> -;; Enable this if you want Samba to be a domain logon server for -;; Windows95 workstations. +# Enable this if you want Samba to be a domain logon server for +# Windows95 workstations. ; domain logons = yes -;; if you enable domain logons then you may want a per-machine or -;; per user logon script -;; run a specific logon batch file per workstation (machine) +# if you enable domain logons then you may want a per-machine or +# per user logon script +# run a specific logon batch file per workstation (machine) ; logon script = %m.bat -;; run a specific logon batch file per username +# run a specific logon batch file per username ; logon script = %u.bat -;; Where to store roving profiles (only for Win95 and WinNT) -;; %L substitutes for this servers netbios name, %U is username -;; You must uncomment the [Profiles] share below +# Where to store roving profiles (only for Win95 and WinNT) +# %L substitutes for this servers netbios name, %U is username +# You must uncomment the [Profiles] share below ; logon path = \\%L\Profiles\%U -;; Windows Internet Name Serving Support Section: -;; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server +# Windows Internet Name Serving Support Section: +# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server ; wins support = yes -;; WINS Server - Tells the NMBD components of Samba to be a WINS Client -;; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both +# WINS Server - Tells the NMBD components of Samba to be a WINS Client +# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both ; wins server = w.x.y.z -;; WINS Proxy - Tells Samba to answer name resolution queries on -;; behalf of a non WINS capable client, for this to work there must be -;; at least one WINS Server on the network. The default is NO. +# WINS Proxy - Tells Samba to answer name resolution queries on +# behalf of a non WINS capable client, for this to work there must be +# at least one WINS Server on the network. The default is NO. ; wins proxy = yes -;;============================ Share Definitions ============================== +#============================ Share Definitions ============================== [homes] comment = Home Directories browseable = no writable = yes -;; Un-comment the following and create the netlogon directory for Domain Logons +# Un-comment the following and create the netlogon directory for Domain Logons ; [netlogon] ; comment = Network Logon Service ; path = /usr/local/samba/lib/netlogon @@ -126,47 +133,47 @@ ; writable = no -;; Un-comment the following to provide a specific roving profile share -;; the default is to use the user's home directory +# Un-comment the following to provide a specific roving profile share +# the default is to use the user's home directory ;[Profiles] ; path = /usr/local/samba/profiles ; browseable = no ; guest ok = yes -;; NOTE: If you have a BSD-style print system there is no need to -;; specifically define each individual printer +# NOTE: If you have a BSD-style print system there is no need to +# specifically define each individual printer [printers] comment = All Printers path = /usr/spool/samba browseable = no -;; Set public = yes to allow user 'guest account' to print +# Set public = yes to allow user 'guest account' to print guest ok = no writable = no printable = yes -;; This one is useful for people to share files +# This one is useful for people to share files ;[tmp] ; comment = Temporary file space ; path = /tmp ; read only = no ; public = yes -;; A publicly accessible directory, but read only, except for people in -;; the users group +# A publicly accessible directory, but read only, except for people in +# the "staff" group ;[public] ; comment = Public Stuff ; path = /home/samba ; public = yes ; writable = yes ; printable = no -; write list = @users +; write list = @staff -;; Other examples. -;; -;; A private printer, usable only by fred. Spool data will be placed in fred's -;; home directory. Note that fred must have write access to the spool directory, -;; wherever it is. +# Other examples. +# +# A private printer, usable only by fred. Spool data will be placed in fred's +# home directory. Note that fred must have write access to the spool directory, +# wherever it is. ;[fredsprn] ; comment = Fred's Printer ; valid users = fred @@ -175,9 +182,9 @@ ; public = no ; writable = no ; printable = yes -; -;; A private directory, usable only by fred. Note that fred requires write -;; access to the directory. + +# A private directory, usable only by fred. Note that fred requires write +# access to the directory. ;[fredsdir] ; comment = Fred's Service ; path = /usr/somewhere/private @@ -185,36 +192,34 @@ ; public = no ; writable = yes ; printable = no -; -;; a service which has a different directory for each machine that connects -;; this allows you to tailor configurations to incoming machines. You could -;; also use the %u option to tailor it by user name. -;; The %m gets replaced with the machine name that is connecting. + +# a service which has a different directory for each machine that connects +# this allows you to tailor configurations to incoming machines. You could +# also use the %u option to tailor it by user name. +# The %m gets replaced with the machine name that is connecting. ;[pchome] ; comment = PC Directories ; path = /usr/pc/%m ; public = no ; writable = yes -; -; -;; A publicly accessible directory, read/write to all users. Note that all files -;; created in the directory by users will be owned by the default user, so -;; any user with access can delete any other user's files. Obviously this -;; directory must be writable by the default user. Another user could of course -;; be specified, in which case all files would be owned by that user instead. + +# A publicly accessible directory, read/write to all users. Note that all files +# created in the directory by users will be owned by the default user, so +# any user with access can delete any other user's files. Obviously this +# directory must be writable by the default user. Another user could of course +# be specified, in which case all files would be owned by that user instead. ;[public] ; path = /usr/somewhere/else/public ; public = yes ; only guest = yes ; writable = yes ; printable = no -; -; -;; The following two entries demonstrate how to share a directory so that two -;; users can place files there that will be owned by the specific users. In this -;; setup, the directory should be writable by both users and should have the -;; sticky bit set on it to prevent abuse. Obviously this could be extended to -;; as many users as required. + +# The following two entries demonstrate how to share a directory so that two +# users can place files there that will be owned by the specific users. In this +# setup, the directory should be writable by both users and should have the +# sticky bit set on it to prevent abuse. Obviously this could be extended to +# as many users as required. ;[myshare] ; comment = Mary's and Fred's stuff ; path = /usr/somewhere/shared -- cgit From 1db26d69c559c9670416b89428f50a8ccd5d4018 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 19 Oct 1997 05:18:09 +0000 Subject: add a section on encryption and change the formatting a bit --- examples/smb.conf.default | 211 ++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 103 deletions(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 0d2c6234c70..9664ac1ab47 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -1,124 +1,131 @@ -;; This is the main Samba configuration file. You should read the -;; smb.conf(5) manual page in order to understand the options listed -;; here. Samba has a huge number of configurable options (perhaps too -;; many!) most of which are not shown in this example - -;; Any line which starts with a ; (semi-colon) is a comment and -;; is ignored - -;; Whenever you modify this file you should run the command "testparm" -;; to check that you have not many any basic syntactic errors. - -;;======================= Global Settings ===================================== +# This is the main Samba configuration file. You should read the +# smb.conf(5) manual page in order to understand the options listed +# here. Samba has a huge number of configurable options (perhaps too +# many!) most of which are not shown in this example +# +# Any line which starts with a ; (semi-colon) or a # (hash) +# is a comment and is ignored. In this example we will use a # +# for commentry and a ; for parts of the config file that you +# may wish to enable +# +# NOTE: Whenever you modify this file you should run the command "testparm" +# to check that you have not many any basic syntactic errors. +# +#======================= Global Settings ===================================== [global] -;; workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 +# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4 workgroup = MYGROUP -;; server string is the equivalent of the NT Description field +# server string is the equivalent of the NT Description field server string = Samba Server -;; This option is important for security. It allows you to restrict -;; connections to machines which are on your local network. The -;; following example restricts access to two C class networks and -;; the "loopback" interface. For more examples of the syntax see -;; the smb.conf man page +# This option is important for security. It allows you to restrict +# connections to machines which are on your local network. The +# following example restricts access to two C class networks and +# the "loopback" interface. For more examples of the syntax see +# the smb.conf man page ; hosts allow = 192.168.1. 192.168.2. 127. -;; if you want to automatically load your printer list rather -;; than setting them up individually then you'll need this +# if you want to automatically load your printer list rather +# than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes -;; Uncomment this if you want a guest account, you must add this to /etc/passwd -;; otherwise the user "nobody" is used +# Uncomment this if you want a guest account, you must add this to /etc/passwd +# otherwise the user "nobody" is used ; guest account = pcguest -;; this tells Samba to use a separate log file for each machine -;; that connects +# this tells Samba to use a separate log file for each machine +# that connects log file = /usr/local/samba/var/log.%m -;; Put a capping on the size of the log files (in Kb). +# Put a capping on the size of the log files (in Kb). max log size = 50 -;; Security mode. Most people will want user level security. See -;; security_level.txt for details. +# Security mode. Most people will want user level security. See +# security_level.txt for details. security = user -;; Use password server option only with security = server +# Use password server option only with security = server ; password server = <NT-Server-Name> -;; Using the following line enables you to customise your configuration -;; on a per machine basis. The %m gets replaced with the netbios name -;; of the machine that is connecting +# You may wish to use password encryption. Please read +# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation. +# Do not enable this option unless you have read those documents +; encrypt passwords = yes + +# Using the following line enables you to customise your configuration +# on a per machine basis. The %m gets replaced with the netbios name +# of the machine that is connecting ; include = /usr/local/samba/lib/smb.conf.%m -;; Most people will find that this option gives better performance. -;; See speed.txt and the manual pages for details +# Most people will find that this option gives better performance. +# See speed.txt and the manual pages for details socket options = TCP_NODELAY -;; Configure Samba to use multiple interfaces -;; If you have multiple network interfaces then you must list them -;; here. See the man page for details. +# Configure Samba to use multiple interfaces +# If you have multiple network interfaces then you must list them +# here. See the man page for details. ; interfaces = 192.168.12.2/24 192.168.13.2/24 -;; Browser Control Options: -;; set local master to no if you don't want Samba to become a master -;; browser on your network. Otherwise the normal election rules apply +# Browser Control Options: +# set local master to no if you don't want Samba to become a master +# browser on your network. Otherwise the normal election rules apply ; local master = no -;; OS Level determines the precedence of this server in master browser -;; elections. The default value should be reasonable +# OS Level determines the precedence of this server in master browser +# elections. The default value should be reasonable ; os level = 33 -;; Domain Master specifies Samba to be the Domain Master Browser. This -;; allows Samba to collate browse lists between subnets. Don't use this -;; if you already have a Windows NT domain controller doing this job +# Domain Master specifies Samba to be the Domain Master Browser. This +# allows Samba to collate browse lists between subnets. Don't use this +# if you already have a Windows NT domain controller doing this job ; domain master = yes -;; Preferred Master causes Samba to force a local browser election on startup -;; and gives it a slightly higher chance of winning the election +# Preferred Master causes Samba to force a local browser election on startup +# and gives it a slightly higher chance of winning the election ; preferred master = yes -;; Use only if you have an NT server on your network that has been -;; configured at install time to be a primary domain controller. +# Use only if you have an NT server on your network that has been +# configured at install time to be a primary domain controller. ; domain controller = <NT-Domain-Controller-SMBName> -;; Enable this if you want Samba to be a domain logon server for -;; Windows95 workstations. +# Enable this if you want Samba to be a domain logon server for +# Windows95 workstations. ; domain logons = yes -;; if you enable domain logons then you may want a per-machine or -;; per user logon script -;; run a specific logon batch file per workstation (machine) +# if you enable domain logons then you may want a per-machine or +# per user logon script +# run a specific logon batch file per workstation (machine) ; logon script = %m.bat -;; run a specific logon batch file per username +# run a specific logon batch file per username ; logon script = %u.bat -;; Where to store roving profiles (only for Win95 and WinNT) -;; %L substitutes for this servers netbios name, %U is username -;; You must uncomment the [Profiles] share below +# Where to store roving profiles (only for Win95 and WinNT) +# %L substitutes for this servers netbios name, %U is username +# You must uncomment the [Profiles] share below ; logon path = \\%L\Profiles\%U -;; Windows Internet Name Serving Support Section: -;; WINS Support - Tells the NMBD component of Samba to enable it's WINS Server +# Windows Internet Name Serving Support Section: +# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server ; wins support = yes -;; WINS Server - Tells the NMBD components of Samba to be a WINS Client -;; Note: Samba can be either a WINS Server, or a WINS Client, but NOT both +# WINS Server - Tells the NMBD components of Samba to be a WINS Client +# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both ; wins server = w.x.y.z -;; WINS Proxy - Tells Samba to answer name resolution queries on -;; behalf of a non WINS capable client, for this to work there must be -;; at least one WINS Server on the network. The default is NO. +# WINS Proxy - Tells Samba to answer name resolution queries on +# behalf of a non WINS capable client, for this to work there must be +# at least one WINS Server on the network. The default is NO. ; wins proxy = yes -;;============================ Share Definitions ============================== +#============================ Share Definitions ============================== [homes] comment = Home Directories browseable = no writable = yes -;; Un-comment the following and create the netlogon directory for Domain Logons +# Un-comment the following and create the netlogon directory for Domain Logons ; [netlogon] ; comment = Network Logon Service ; path = /usr/local/samba/lib/netlogon @@ -126,47 +133,47 @@ ; writable = no -;; Un-comment the following to provide a specific roving profile share -;; the default is to use the user's home directory +# Un-comment the following to provide a specific roving profile share +# the default is to use the user's home directory ;[Profiles] ; path = /usr/local/samba/profiles ; browseable = no ; guest ok = yes -;; NOTE: If you have a BSD-style print system there is no need to -;; specifically define each individual printer +# NOTE: If you have a BSD-style print system there is no need to +# specifically define each individual printer [printers] comment = All Printers path = /usr/spool/samba browseable = no -;; Set public = yes to allow user 'guest account' to print +# Set public = yes to allow user 'guest account' to print guest ok = no writable = no printable = yes -;; This one is useful for people to share files +# This one is useful for people to share files ;[tmp] ; comment = Temporary file space ; path = /tmp ; read only = no ; public = yes -;; A publicly accessible directory, but read only, except for people in -;; the users group +# A publicly accessible directory, but read only, except for people in +# the "staff" group ;[public] ; comment = Public Stuff ; path = /home/samba ; public = yes ; writable = yes ; printable = no -; write list = @users +; write list = @staff -;; Other examples. -;; -;; A private printer, usable only by fred. Spool data will be placed in fred's -;; home directory. Note that fred must have write access to the spool directory, -;; wherever it is. +# Other examples. +# +# A private printer, usable only by fred. Spool data will be placed in fred's +# home directory. Note that fred must have write access to the spool directory, +# wherever it is. ;[fredsprn] ; comment = Fred's Printer ; valid users = fred @@ -175,9 +182,9 @@ ; public = no ; writable = no ; printable = yes -; -;; A private directory, usable only by fred. Note that fred requires write -;; access to the directory. + +# A private directory, usable only by fred. Note that fred requires write +# access to the directory. ;[fredsdir] ; comment = Fred's Service ; path = /usr/somewhere/private @@ -185,36 +192,34 @@ ; public = no ; writable = yes ; printable = no -; -;; a service which has a different directory for each machine that connects -;; this allows you to tailor configurations to incoming machines. You could -;; also use the %u option to tailor it by user name. -;; The %m gets replaced with the machine name that is connecting. + +# a service which has a different directory for each machine that connects +# this allows you to tailor configurations to incoming machines. You could +# also use the %u option to tailor it by user name. +# The %m gets replaced with the machine name that is connecting. ;[pchome] ; comment = PC Directories ; path = /usr/pc/%m ; public = no ; writable = yes -; -; -;; A publicly accessible directory, read/write to all users. Note that all files -;; created in the directory by users will be owned by the default user, so -;; any user with access can delete any other user's files. Obviously this -;; directory must be writable by the default user. Another user could of course -;; be specified, in which case all files would be owned by that user instead. + +# A publicly accessible directory, read/write to all users. Note that all files +# created in the directory by users will be owned by the default user, so +# any user with access can delete any other user's files. Obviously this +# directory must be writable by the default user. Another user could of course +# be specified, in which case all files would be owned by that user instead. ;[public] ; path = /usr/somewhere/else/public ; public = yes ; only guest = yes ; writable = yes ; printable = no -; -; -;; The following two entries demonstrate how to share a directory so that two -;; users can place files there that will be owned by the specific users. In this -;; setup, the directory should be writable by both users and should have the -;; sticky bit set on it to prevent abuse. Obviously this could be extended to -;; as many users as required. + +# The following two entries demonstrate how to share a directory so that two +# users can place files there that will be owned by the specific users. In this +# setup, the directory should be writable by both users and should have the +# sticky bit set on it to prevent abuse. Obviously this could be extended to +# as many users as required. ;[myshare] ; comment = Mary's and Fred's stuff ; path = /usr/somewhere/shared -- cgit From 2f2d18cc9474e1b40765a67242659be7c63a9936 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 19 Oct 1997 12:24:23 +0000 Subject: pipes.c pipesrvsvc.c : moved stub srvsvc pipe function into separate file, in preparation for further work. --- source/pipesrvsvc.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ source/smbd/pipes.c | 80 ------------------------------------- 2 files changed, 113 insertions(+), 80 deletions(-) create mode 100644 source/pipesrvsvc.c diff --git a/source/pipesrvsvc.c b/source/pipesrvsvc.c new file mode 100644 index 00000000000..a3941e318c6 --- /dev/null +++ b/source/pipesrvsvc.c @@ -0,0 +1,113 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Pipe SMB reply routines - srvsvc pipe + Copyright (C) Andrew Tridgell 1992-1997, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + Copyright (C) Paul Ashton 1997. + + 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 "trans2.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + +BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) +{ + uint16 opnum; + char *q; + int pkttype; + extern pstring myname; + char *servername; + uint32 level; + + opnum = SVAL(data,22); + + pkttype = CVAL(data, 2); + if (pkttype == 0x0b) /* RPC BIND */ + { + DEBUG(4,("srvsvc rpc bind %x\n",pkttype)); + LsarpcTNP1(data,rdata,rdata_len); + return True; + } + + DEBUG(4,("srvsvc TransactNamedPipe op %x\n",opnum)); + initrpcreply(data, *rdata); + DEBUG(4,("srvsvc LINE %d\n",__LINE__)); + get_myname(myname,NULL); + + switch (opnum) + { + case NETSHAREENUM: + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, level); q += 4; + SIVAL(q, 0, 1); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; + SIVAL(q, 0, 2); q += 4; /* number of entries */ + SIVAL(q, 0, 2); q += 4; + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + + case NETSERVERGETINFO: + { + UNISTR2 uni_str; + q = data + 0x18; + servername = q + 16; + q = skip_unicode_string(servername,1); + if (strlen(unistr(servername)) % 2 == 0) + q += 2; + level = IVAL(q, 0); q += 4; + /* ignore the rest for the moment */ + q = *rdata + 0x18; + SIVAL(q, 0, 101); q += 4; /* switch value */ + SIVAL(q, 0, 2); q += 4; /* bufptr */ + SIVAL(q, 0, 0x1f4); q += 4; /* platform id */ + SIVAL(q, 0, 2); q += 4; /* bufptr for name */ + SIVAL(q, 0, 5); q += 4; /* major version */ + SIVAL(q, 0, 4); q += 4; /* minor version == 5.4 */ + SIVAL(q, 0, 0x4100B); q += 4; /* type */ + SIVAL(q, 0, 2); q += 4; /* comment */ + make_unistr2(&uni_str, myname, strlen(myname)); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + make_unistr2(&uni_str, lp_serverstring(), strlen(lp_serverstring())); + q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); + + q = align_offset(q, *rdata, 4); + + endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + break; + } + default: + DEBUG(4, ("srvsvc, unknown code: %lx\n", opnum)); + } + return(True); +} + diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index 8c7e6c69c5c..12e54d2bcad 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -364,83 +364,3 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } -BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum; - char *q; - int pkttype; - extern pstring myname; - char *servername; - uint32 level; - - opnum = SVAL(data,22); - - pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("srvsvc rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("srvsvc TransactNamedPipe op %x\n",opnum)); - initrpcreply(data, *rdata); - DEBUG(4,("srvsvc LINE %d\n",__LINE__)); - get_myname(myname,NULL); - switch (opnum) - { - case NETSHAREENUM: - q = data + 0x18; - servername = q + 16; - q = skip_unicode_string(servername,1); - if (strlen(unistr(servername)) % 2 == 0) - q += 2; - level = IVAL(q, 0); q += 4; - /* ignore the rest for the moment */ - q = *rdata + 0x18; - SIVAL(q, 0, level); q += 4; - SIVAL(q, 0, 1); q += 4; /* switch value */ - SIVAL(q, 0, 2); q += 4; - SIVAL(q, 0, 2); q += 4; /* number of entries */ - SIVAL(q, 0, 2); q += 4; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - case NETSERVERGETINFO: - { - UNISTR2 uni_str; - q = data + 0x18; - servername = q + 16; - q = skip_unicode_string(servername,1); - if (strlen(unistr(servername)) % 2 == 0) - q += 2; - level = IVAL(q, 0); q += 4; - /* ignore the rest for the moment */ - q = *rdata + 0x18; - SIVAL(q, 0, 101); q += 4; /* switch value */ - SIVAL(q, 0, 2); q += 4; /* bufptr */ - SIVAL(q, 0, 0x1f4); q += 4; /* platform id */ - SIVAL(q, 0, 2); q += 4; /* bufptr for name */ - SIVAL(q, 0, 5); q += 4; /* major version */ - SIVAL(q, 0, 4); q += 4; /* minor version == 5.4 */ - SIVAL(q, 0, 0x4100B); q += 4; /* type */ - SIVAL(q, 0, 2); q += 4; /* comment */ - make_unistr2(&uni_str, myname, strlen(myname)); - q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); - - make_unistr2(&uni_str, lp_serverstring(), strlen(lp_serverstring())); - q = smb_io_unistr2(False, &uni_str, q, *rdata, 4, 0); - - q = align_offset(q, *rdata, 4); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - break; - } - default: - DEBUG(4, ("srvsvc, unknown code: %lx\n", opnum)); - } - return(True); -} - -- cgit From 7d8c0b60f19fb503619e3bdcde7aaa144e56dcd4 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Sun, 19 Oct 1997 12:28:00 +0000 Subject: Added comment submitted by Frank Varnavas. --- docs/textdocs/WinNT.txt | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/textdocs/WinNT.txt b/docs/textdocs/WinNT.txt index d5810535971..d85f9966bc7 100644 --- a/docs/textdocs/WinNT.txt +++ b/docs/textdocs/WinNT.txt @@ -1,7 +1,8 @@ Contributors: Various Password Section - Copyright (C) 1997 - John H Terpstra Printing Section - Copyright (C) 1997 - Matthew Harrell -Updated: August 20, 1997 + Priting Info - Copyright (C) 1997 - Frank Varnavas +Updated: October 16, 1997 Status: Current Subject: Samba and Windows NT Password Handling @@ -72,3 +73,32 @@ time for the NT machine to get verification that the printer queue actually exists. I hope this helped in some way... + +===================================================================== +Printing Info: +-------------- + +From: Frank Varnavas <varnavas@ny.ubs.com> +Subject: RE: Samba as a print server + +When an NT client attempts to connect to a printer on a non-NT print +server the attempt is failed with an error, something like: + + "You have insufficient access to your computer to perform the + operation because a driver needs to be installed" + +This is because domain users must have 'Power User' status on the +desktop to connect to printers on a non-NT print server. + +This error occurs regardless of whether the driver in question is +already installed or not. What it really means is that the server is +a non-NT server and the client does not have permission to create +printers locally. Apparently when a connection to a non-NT print +server is made the printer is defined locally. Such an action can be +performed by either a local administrator or a Power User. +Unfortunately there is no way to limit the powers of a Power User, nor +is there any way to grant the Printer Creation right to another group. + +This permission policy is documented in PSS database WINNT, ID Q101874 + +Frank Varnavas (varnavas@ny.ubs.com) -- cgit From 1f1bc840157001ae494b034398fc85aead438fb7 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Sun, 19 Oct 1997 12:38:46 +0000 Subject: Added Frank Varnavas comments. --- docs/textdocs/WinNT.txt | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/textdocs/WinNT.txt b/docs/textdocs/WinNT.txt index d5810535971..d85f9966bc7 100644 --- a/docs/textdocs/WinNT.txt +++ b/docs/textdocs/WinNT.txt @@ -1,7 +1,8 @@ Contributors: Various Password Section - Copyright (C) 1997 - John H Terpstra Printing Section - Copyright (C) 1997 - Matthew Harrell -Updated: August 20, 1997 + Priting Info - Copyright (C) 1997 - Frank Varnavas +Updated: October 16, 1997 Status: Current Subject: Samba and Windows NT Password Handling @@ -72,3 +73,32 @@ time for the NT machine to get verification that the printer queue actually exists. I hope this helped in some way... + +===================================================================== +Printing Info: +-------------- + +From: Frank Varnavas <varnavas@ny.ubs.com> +Subject: RE: Samba as a print server + +When an NT client attempts to connect to a printer on a non-NT print +server the attempt is failed with an error, something like: + + "You have insufficient access to your computer to perform the + operation because a driver needs to be installed" + +This is because domain users must have 'Power User' status on the +desktop to connect to printers on a non-NT print server. + +This error occurs regardless of whether the driver in question is +already installed or not. What it really means is that the server is +a non-NT server and the client does not have permission to create +printers locally. Apparently when a connection to a non-NT print +server is made the printer is defined locally. Such an action can be +performed by either a local administrator or a Power User. +Unfortunately there is no way to limit the powers of a Power User, nor +is there any way to grant the Printer Creation right to another group. + +This permission policy is documented in PSS database WINNT, ID Q101874 + +Frank Varnavas (varnavas@ny.ubs.com) -- cgit From e8bedb18bf249d2f06834b0f151ea22df86e2602 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 19 Oct 1997 14:36:27 +0000 Subject: added the following structures: SH_INFO_1 SH_INFO_1_STR SHARE_INFO_1_CTR SRV_Q_NET_SHARE_ENUM SRV_R_NET_SHARE_ENUM the share info1 container can handle a maximum of 32 shares. the share info1 string structures contain two unicode strings, with 1024 uint16 characters _each_. we're going to _have_ to dynamically allocate the unicode strings, else we'll run out of stack space. rapidly. --- source/include/smb.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/source/include/smb.h b/source/include/smb.h index 11ec6940a66..facb059f369 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -836,6 +836,72 @@ typedef struct lsa_r_sam_logoff_info } LSA_R_SAM_LOGOFF; + +/* SH_INFO_1 (pointers to level 1 share info strings) */ +typedef struct ptr_share_info1 +{ + uint32 ptr_shi1_netname; /* pointer to net name. */ + uint32 shi1_type; /* type of share. 0 - undocumented. */ + uint32 ptr_shi1_remark; /* pointer to comment. */ + +} SH_INFO_1; + +/* SH_INFO_1_STR (level 1 share info strings) */ +typedef struct str_share_info1 +{ + UNISTR2 uni_shi1_netname; /* unicode string of net name */ + UNISTR2 uni_shi1_remark; /* unicode string of comment. */ + +} SH_INFO_1_STR; + +/* oops - this is going to take up a *massive* amount of stack. */ +/* the UNISTR2s already have 1024 uint16 chars in them... */ +#define MAX_SHARE_ENTRIES 32 + +/* SHARE_INFO_1_CONTAINER */ +typedef struct share_info_ctr +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_share_info; /* Buffer */ + SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */ + SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */ + uint32 num_entries_read2; /* EntriesRead2 */ + +} SHARE_INFO_1_CTR; + + +/* SRV_Q_NET_SHARE_ENUM */ +typedef struct q_net_share_enum_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* server name */ + + uint32 share_level; /* share level */ + uint32 switch_value; /* switch value */ + + uint32* ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ + SHARE_INFO_1_CTR share_info; /* share info with 0 entries */ + + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + +} SRV_Q_NET_SHARE_ENUM; + + +/* SRV_R_NET_SHARE_ENUM */ +typedef struct r_net_share_enum_info +{ + uint32 share_level; /* share level */ + uint32 switch_value; /* switch value */ + + uint32* ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ + SHARE_INFO_1_CTR share_info; /* share info with 0 entries */ + + uint32 status; /* return status */ + +} SRV_R_NET_SHARE_ENUM; + + + /* Yet to be turned into structures: @@ -931,6 +997,7 @@ typedef struct time_t atime; time_t ctime; pstring name; + } file_info; -- cgit From 22b86b6499b2680d16cb4180a736b4e750147409 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 19 Oct 1997 15:33:25 +0000 Subject: Makefile : added srvparse.o and pipesrvsvc.o smb.h : mods to the Net Share Enum stuff srvparse.c : Net Share Enum parsing support. more srvsvc pipe parsing to go here... pipenetlog.c util.c: modified standard_sub_basic() so that you can set a global boolean and use a different string for the %U username substitution. proto.h: the usual. --- source/include/proto.h | 9 +++ source/include/smb.h | 28 ++++--- source/lib/util.c | 78 +++++++++++-------- source/pipenetlog.c | 15 +++- source/srvparse.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 285 insertions(+), 44 deletions(-) create mode 100644 source/srvparse.c diff --git a/source/include/proto.h b/source/include/proto.h index e0ddee89439..aee8a86d05a 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -651,6 +651,9 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); + +/*The following definitions come from pipesrvsvc.c */ + BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -884,6 +887,12 @@ struct smb_passwd *get_smbpwnam(char *name); /*The following definitions come from smbrun.c */ +/*The following definitions come from srvparse.c */ + +char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth); +char* srv_io_r_net_share_enum(BOOL io, SRV_R_NET_SHARE_ENUM *r_n, char *q, char *base, int align, int depth); +char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth); + /*The following definitions come from status.c */ void Ucrit_addUsername(pstring username); diff --git a/source/include/smb.h b/source/include/smb.h index facb059f369..d847c6f3420 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -565,6 +565,7 @@ typedef struct lsa_r_query_info { DOM_QUERY_3 id3; DOM_QUERY_5 id5; + } dom; uint32 status; /* return code */ @@ -840,17 +841,17 @@ typedef struct lsa_r_sam_logoff_info /* SH_INFO_1 (pointers to level 1 share info strings) */ typedef struct ptr_share_info1 { - uint32 ptr_shi1_netname; /* pointer to net name. */ - uint32 shi1_type; /* type of share. 0 - undocumented. */ - uint32 ptr_shi1_remark; /* pointer to comment. */ + uint32 ptr_netname; /* pointer to net name. */ + uint32 type; /* type of share. 0 - undocumented. */ + uint32 ptr_remark; /* pointer to comment. */ } SH_INFO_1; /* SH_INFO_1_STR (level 1 share info strings) */ typedef struct str_share_info1 { - UNISTR2 uni_shi1_netname; /* unicode string of net name */ - UNISTR2 uni_shi1_remark; /* unicode string of comment. */ + UNISTR2 uni_netname; /* unicode string of net name */ + UNISTR2 uni_remark; /* unicode string of comment. */ } SH_INFO_1_STR; @@ -879,8 +880,13 @@ typedef struct q_net_share_enum_info uint32 share_level; /* share level */ uint32 switch_value; /* switch value */ - uint32* ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ - SHARE_INFO_1_CTR share_info; /* share info with 0 entries */ + uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ + + union + { + SHARE_INFO_1_CTR info1; /* share info with 0 entries */ + + } share; uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ @@ -893,8 +899,12 @@ typedef struct r_net_share_enum_info uint32 share_level; /* share level */ uint32 switch_value; /* switch value */ - uint32* ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ - SHARE_INFO_1_CTR share_info; /* share info with 0 entries */ + uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ + union + { + SHARE_INFO_1_CTR info1; /* share info container */ + + } share; uint32 status; /* return status */ diff --git a/source/lib/util.c b/source/lib/util.c index b69b30d20cd..36e9e326acf 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -72,7 +72,12 @@ static enum remote_arch_types ra_type = RA_UNKNOWN; fstring remote_proto="UNKNOWN"; pstring myhostname=""; pstring user_socket_options=""; + pstring sesssetup_user=""; +pstring samlogon_user=""; + +BOOL sam_logon_in_ssb = False; + pstring myname = ""; fstring myworkgroup = ""; char **my_netbios_names; @@ -3603,38 +3608,49 @@ Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and Paul Rippin <pr3245@nopc.eurostat.cec.be> ********************************************************************/ void standard_sub_basic(char *str) - { - char *s, *p; - char pidstr[10]; - struct passwd *pass; +{ + char *s, *p; + char pidstr[10]; + struct passwd *pass; + char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user; - for (s = str ; (p = strchr(s,'%')) != NULL ; s = p ) - { - switch (*(p+1)) - { - case 'G' : if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL) - string_sub(p,"%G",gidtoname(pass->pw_gid)); - else - p += 2; - break; - case 'I' : string_sub(p,"%I",client_addr()); break; - case 'L' : string_sub(p,"%L",local_machine); break; - case 'M' : string_sub(p,"%M",client_name()); break; - case 'R' : string_sub(p,"%R",remote_proto); break; - case 'T' : string_sub(p,"%T",timestring()); break; - case 'U' : string_sub(p,"%U",sesssetup_user); break; - case 'a' : string_sub(p,"%a",remote_arch); break; - case 'd' : sprintf(pidstr,"%d",(int)getpid()); - string_sub(p,"%d",pidstr); - break; - case 'h' : string_sub(p,"%h",myhostname); break; - case 'm' : string_sub(p,"%m",remote_machine); break; - case 'v' : string_sub(p,"%v",VERSION); break; - case '\0' : p++; break; /* don't run off end if last character is % */ - default : p+=2; break; - } - } - return; + for (s = str ; (p = strchr(s,'%')) != NULL ; s = p ) + { + switch (*(p+1)) + { + case 'G' : + { + if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL) + { + string_sub(p,"%G",gidtoname(pass->pw_gid)); + } + else + { + p += 2; + } + break; + } + case 'I' : string_sub(p,"%I", client_addr()); break; + case 'L' : string_sub(p,"%L", local_machine); break; + case 'M' : string_sub(p,"%M", client_name()); break; + case 'R' : string_sub(p,"%R", remote_proto); break; + case 'T' : string_sub(p,"%T", timestring()); break; + case 'U' : string_sub(p,"%U", username); break; + case 'a' : string_sub(p,"%a", remote_arch); break; + case 'd' : + { + sprintf(pidstr,"%d",(int)getpid()); + string_sub(p,"%d", pidstr); + break; + } + case 'h' : string_sub(p,"%h", myhostname); break; + case 'm' : string_sub(p,"%m", remote_machine); break; + case 'v' : string_sub(p,"%v", VERSION); break; + case '\0': p++; break; /* don't run off end if last character is % */ + default : p+=2; break; + } + } + return; } /******************************************************************* diff --git a/source/pipenetlog.c b/source/pipenetlog.c index f2916207969..0dac8048346 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -32,6 +32,8 @@ extern int DEBUGLEVEL; +extern BOOL sam_logon_in_ssb; +extern pstring samlogon_user; #ifdef NTDOMAIN @@ -505,7 +507,6 @@ static void api_lsa_sam_logon( user_struct *vuser, pstring my_name; pstring my_workgroup; pstring dom_sid; - pstring username; extern pstring myname; dummy_time.low = 0xffffffff; @@ -513,12 +514,16 @@ static void api_lsa_sam_logon( user_struct *vuser, get_myname(myname, NULL); + pstrcpy(samlogon_user, unistr2(q_l.sam_id.auth.id1.uni_user_name.buffer)); + + /* hack to get standard_sub_basic() to use the sam logon username */ + sam_logon_in_ssb = True; + pstrcpy(logon_script, lp_logon_script()); pstrcpy(profile_path, lp_logon_path ()); pstrcpy(dom_sid , lp_domainsid ()); pstrcpy(my_workgroup, lp_workgroup ()); - pstrcpy(username, unistr2(q_l.sam_id.auth.id1.uni_user_name.buffer)); pstrcpy(my_name , myname ); strupper(my_name); @@ -528,8 +533,10 @@ static void api_lsa_sam_logon( user_struct *vuser, pstrcpy(home_dir , vuser->home_share); #else pstrcpy(home_dir , "\\\\%L\\%U"); - standard_sub_basic(home_dir); #endif + standard_sub_basic(home_dir); + + sam_logon_in_ssb = False; make_lsa_user_info(&usr_info, @@ -540,7 +547,7 @@ static void api_lsa_sam_logon( user_struct *vuser, &dummy_time, /* pass_can_change_time */ &dummy_time, /* pass_must_change_time */ - username, /* user_name */ + samlogon_user, /* user_name */ vuser->real_name, /* full_name */ logon_script, /* logon_script */ profile_path, /* profile_path */ diff --git a/source/srvparse.c b/source/srvparse.c new file mode 100644 index 00000000000..c06ff40ceb8 --- /dev/null +++ b/source/srvparse.c @@ -0,0 +1,199 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba utility functions + Copyright (C) Luke Leighton 1996 - 1997 Paul Ashton 1997 + + 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 DEBUGLEVEL; + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* srv_io_share_info1_str(BOOL io, SH_INFO_1_STR *sh1, char *q, char *base, int align, int depth) +{ + if (sh1 == NULL) return NULL; + + DEBUG(5,("%s%04x srv_io_share_info1_str\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + q = smb_io_unistr2(io, &(sh1->uni_netname), q, base, align, depth); + q = smb_io_unistr2(io, &(sh1->uni_remark ), q, base, align, depth); + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* srv_io_share_info1(BOOL io, SH_INFO_1 *sh1, char *q, char *base, int align, int depth) +{ + if (sh1 == NULL) return NULL; + + DEBUG(5,("%s%04x srv_io_share_info1\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("ptr_netname", depth, base, io, q, sh1->ptr_netname); q += 4; + DBG_RW_IVAL("type ", depth, base, io, q, sh1->type ); q += 4; + DBG_RW_IVAL("ptr_remark ", depth, base, io, q, sh1->ptr_remark); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, int align, int depth) +{ + if (ctr == NULL) return NULL; + + DEBUG(5,("%s%04x srv_io_share_1_ctr\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("num_entries_read", depth, base, io, q, ctr->num_entries_read); q += 4; + DBG_RW_IVAL("ptr_share_info", depth, base, io, q, ctr->ptr_share_info); q += 4; + + if (ctr->ptr_share_info != 0) + { + int i; + int max_entries = ctr->num_entries_read; + if (max_entries > MAX_SHARE_ENTRIES) + { + max_entries = MAX_SHARE_ENTRIES; /* report this! */ + } + + for (i = 0; i < max_entries; i++) + { + q = srv_io_share_info1(io, &(ctr->info_1[i]), q, base, align, depth); + } + + for (i = 0; i < max_entries; i++) + { + q = srv_io_share_info1_str(io, &(ctr->info_1_str[i]), q, base, align, depth); + } + + DBG_RW_IVAL("num_entries_read2", depth, base, io, q, ctr->num_entries_read); q += 4; + } + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth) +{ + if (q_n == NULL) return NULL; + + DEBUG(5,("%s%04x srv_io_q_net_share_enum\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("ptr_srv_name", depth, base, io, q, q_n->ptr_srv_name); q += 4; + q = smb_io_unistr2(io, &(q_n->uni_srv_name), q, base, align, depth); + + q = align_offset(q, base, align); + + DBG_RW_IVAL("share_level ", depth, base, io, q, q_n->share_level); q += 4; + DBG_RW_IVAL("switch_value ", depth, base, io, q, q_n->switch_value); q += 4; + + DBG_RW_IVAL("ptr_share_info", depth, base, io, q, q_n->ptr_share_info); q += 4; + if (q_n->ptr_share_info != 0) + { + switch (q_n->switch_value) + { + case 1: + { + q = srv_io_share_1_ctr(io, &(q_n->share.info1), q, base, align, depth); + break; + } + default: + { + DEBUG(5,("%s% no share info at switch_value %d\n", + tab_depth(depth), q_n->switch_value)); + break; + } + } + } + DBG_RW_IVAL("preferred_len ", depth, base, io, q, q_n->preferred_len); q += 4; + + return q; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +char* srv_io_r_net_share_enum(BOOL io, SRV_R_NET_SHARE_ENUM *r_n, char *q, char *base, int align, int depth) +{ + if (r_n == NULL) return NULL; + + DEBUG(5,("%s%04x srv_io_q_net_share_enum\n", tab_depth(depth), PTR_DIFF(q, base))); + depth++; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("share_level ", depth, base, io, q, r_n->share_level); q += 4; + DBG_RW_IVAL("switch_value ", depth, base, io, q, r_n->switch_value); q += 4; + + DBG_RW_IVAL("ptr_share_info", depth, base, io, q, r_n->ptr_share_info); q += 4; + if (r_n->ptr_share_info != 0) + { + switch (r_n->switch_value) + { + case 1: + { + q = srv_io_share_1_ctr(io, &(r_n->share.info1), q, base, align, depth); + break; + } + default: + { + DEBUG(5,("%s% no share info at switch_value %d\n", + tab_depth(depth), r_n->switch_value)); + break; + } + } + } + DBG_RW_IVAL("status ", depth, base, io, q, r_n->status); q += 4; + + return q; +} + +#if 0 +/******************************************************************* +reads or writes a structure. +********************************************************************/ + char* lsa_io_(BOOL io, *, char *q, char *base, int align, int depth) +{ + if (== NULL) return NULL; + + q = align_offset(q, base, align); + + DBG_RW_IVAL("", depth, base, io, q, ); q += 4; + + return q; +} +#endif -- cgit From 0a191ee5047b2c81c7adb0554c39ec43d8690230 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 19 Oct 1997 17:01:06 +0000 Subject: creating NetShareEnum parsing / reply creation. compiles, but untested. --- source/include/smb.h | 9 +-- source/pipesrvsvc.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++----- source/srvparse.c | 10 +-- 3 files changed, 163 insertions(+), 25 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index d847c6f3420..7fa19eaa19a 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -156,10 +156,11 @@ implemented */ #define DENY_FCB 7 /* share types */ -#define STYPE_DISKTREE 0 /* Disk drive */ -#define STYPE_PRINTQ 1 /* Spooler queue */ -#define STYPE_DEVICE 2 /* Serial device */ -#define STYPE_IPC 3 /* Interprocess communication (IPC) */ +#define STYPE_DISKTREE 0 /* Disk drive */ +#define STYPE_PRINTQ 1 /* Spooler queue */ +#define STYPE_DEVICE 2 /* Serial device */ +#define STYPE_IPC 3 /* Interprocess communication (IPC) */ +#define STYPE_HIDDEN 0x80000000 /* share is a hidden one (ends with $) */ /* SMB X/Open error codes for the ERRdos error class */ #define ERRbadfunc 1 /* Invalid function (or system call) */ diff --git a/source/pipesrvsvc.c b/source/pipesrvsvc.c index a3941e318c6..10c8d97e757 100644 --- a/source/pipesrvsvc.c +++ b/source/pipesrvsvc.c @@ -29,6 +29,153 @@ extern int DEBUGLEVEL; +/******************************************************************* +********************************************************************/ +static void make_srv_share_info1_str(SH_INFO_1_STR *sh1, char *net_name, char *remark) +{ + if (sh1 == NULL) return; + + DEBUG(5,("make_srv_share_info1_str: %s %s\n", net_name, remark)); + + make_unistr2(&(sh1->uni_netname), net_name, strlen(net_name)); + make_unistr2(&(sh1->uni_remark ), remark , strlen(remark )); +} + +/******************************************************************* +********************************************************************/ +static void make_srv_share_info1(SH_INFO_1 *sh1, char *net_name, uint32 type, char *remark) +{ + if (sh1 == NULL) return; + + DEBUG(5,("make_srv_share_info1_str: %s %8x %s\n", net_name, type, remark)); + + sh1->ptr_netname = net_name != NULL ? 1 : 0; + sh1->type = type; + sh1->ptr_remark = remark != NULL ? 1 : 0; +} + +/******************************************************************* +fill in a share info level 1 structure. + +this function breaks the rule that i'd like to be in place, namely +it doesn't receive its data as arguments: it has to call lp_xxxx() +functions itself. yuck. + +this function is identical to api_RNetShareEnum(). maybe it even +generates the same output! (too much to hope for, really...) + +********************************************************************/ +static void make_srv_share_1_ctr(SHARE_INFO_1_CTR *ctr) +{ + int snum; + int num_entries = 0; + int svcs = lp_numservices(); + + if (ctr == NULL) return; + + DEBUG(5,("make_srv_share_1_ctr\n")); + + for (snum = 0; snum < svcs && num_entries < MAX_SHARE_ENTRIES; num_entries++, snum++) + { + int len_net_name; + pstring net_name; + pstring remark; + uint32 type; + + if (lp_browseable(snum) && lp_snum_ok(snum)) + { + /* see ipc.c:fill_share_info() */ + + pstrcpy(net_name, lp_servicename(snum)); + pstrcpy(remark , lp_comment (snum)); + len_net_name = strlen(net_name); + + /* work out the share type */ + type = STYPE_DISKTREE; + + if (lp_print_ok(snum)) type = STYPE_PRINTQ; + if (strequal("IPC$", net_name)) type = STYPE_IPC; + if (net_name[len_net_name] == '$') type |= STYPE_HIDDEN; + + make_srv_share_info1 (&(ctr->info_1 [num_entries]), net_name, type, remark); + make_srv_share_info1_str(&(ctr->info_1_str[num_entries]), net_name, remark); + } + } + + ctr->num_entries_read = num_entries; + ctr->ptr_share_info = num_entries > 0 ? 1 : 0; + ctr->num_entries_read2 = num_entries; +} + +/******************************************************************* +********************************************************************/ +static void make_srv_net_share_enum(SRV_R_NET_SHARE_ENUM *r_n, + int share_level, int switch_value, int status) +{ + DEBUG(5,("make_srv_net_share_enum: %d\n", __LINE__)); + + r_n->share_level = share_level; + r_n->switch_value = switch_value; + r_n->status = status; + + switch (switch_value) + { + case 1: + { + make_srv_share_1_ctr(&(r_n->share.info1)); + r_n->ptr_share_info = r_n->share.info1.num_entries_read > 0 ? 1 : 0; + break; + } + default: + { + DEBUG(5,("make_srv_net_share_enum: unsupported switch value %d\n", + switch_value)); + r_n->ptr_share_info = 0; + break; + } + } +} + +/******************************************************************* +********************************************************************/ +static int srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, + char *q, char *base, + int status) +{ + SRV_R_NET_SHARE_ENUM r_n; + + DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); + + /* set up the */ + make_srv_net_share_enum(&r_n, q_n->share_level, q_n->switch_value, status); + + /* store the response in the SMB stream */ + q = srv_io_r_net_share_enum(False, &r_n, q, base, 4, 0); + + DEBUG(5,("srv_srv_pwset: %d\n", __LINE__)); + + /* return length of SMB data stored */ + return PTR_DIFF(q, base); +} + +/******************************************************************* +********************************************************************/ +static void api_srv_net_share_info( char *param, char *data, + char **rdata, int *rdata_len ) +{ + SRV_Q_NET_SHARE_ENUM q_n; + + /* grab the net share enum */ + srv_io_q_net_share_enum(True, &q_n, data + 0x18, data, 4, 0); + + /* construct reply. always indicate success */ + *rdata_len = srv_reply_net_share_enum(&q_n, *rdata + 0x18, *rdata, 0x0); +} + + +/******************************************************************* +receives a srvsvc pipe and responds. +********************************************************************/ BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -38,8 +185,6 @@ BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, char *q; int pkttype; extern pstring myname; - char *servername; - uint32 level; opnum = SVAL(data,22); @@ -59,24 +204,16 @@ BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, switch (opnum) { case NETSHAREENUM: - q = data + 0x18; - servername = q + 16; - q = skip_unicode_string(servername,1); - if (strlen(unistr(servername)) % 2 == 0) - q += 2; - level = IVAL(q, 0); q += 4; - /* ignore the rest for the moment */ - q = *rdata + 0x18; - SIVAL(q, 0, level); q += 4; - SIVAL(q, 0, 1); q += 4; /* switch value */ - SIVAL(q, 0, 2); q += 4; - SIVAL(q, 0, 2); q += 4; /* number of entries */ - SIVAL(q, 0, 2); q += 4; - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); + { + api_srv_net_share_info( param, data, rdata, rdata_len); + make_rpc_reply(data, *rdata, *rdata_len); break; + } case NETSERVERGETINFO: { + char *servername; + uint32 level; UNISTR2 uni_str; q = data + 0x18; servername = q + 16; diff --git a/source/srvparse.c b/source/srvparse.c index c06ff40ceb8..a94efff1384 100644 --- a/source/srvparse.c +++ b/source/srvparse.c @@ -79,18 +79,18 @@ char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, in if (ctr->ptr_share_info != 0) { int i; - int max_entries = ctr->num_entries_read; - if (max_entries > MAX_SHARE_ENTRIES) + int num_entries = ctr->num_entries_read; + if (num_entries > MAX_SHARE_ENTRIES) { - max_entries = MAX_SHARE_ENTRIES; /* report this! */ + num_entries = MAX_SHARE_ENTRIES; /* report this! */ } - for (i = 0; i < max_entries; i++) + for (i = 0; i < num_entries; i++) { q = srv_io_share_info1(io, &(ctr->info_1[i]), q, base, align, depth); } - for (i = 0; i < max_entries; i++) + for (i = 0; i < num_entries; i++) { q = srv_io_share_info1_str(io, &(ctr->info_1_str[i]), q, base, align, depth); } -- cgit From 80523a3e83191c9e0b930fc71bd502a94a6f1b19 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Sun, 19 Oct 1997 17:54:13 +0000 Subject: debugging the srvsvc Net Share Enum. some padding issues; some string length issues. it works! --- source/include/smb.h | 4 +++- source/pipesrvsvc.c | 8 +++++--- source/srvparse.c | 6 +++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index 7fa19eaa19a..0d10bd58954 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -865,9 +865,11 @@ typedef struct share_info_ctr { uint32 num_entries_read; /* EntriesRead */ uint32 ptr_share_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */ SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */ - uint32 num_entries_read2; /* EntriesRead2 */ + uint32 num_entries_read3; /* EntriesRead2 */ + uint32 padding; /* padding */ } SHARE_INFO_1_CTR; diff --git a/source/pipesrvsvc.c b/source/pipesrvsvc.c index 10c8d97e757..28a304ef4a1 100644 --- a/source/pipesrvsvc.c +++ b/source/pipesrvsvc.c @@ -37,8 +37,8 @@ static void make_srv_share_info1_str(SH_INFO_1_STR *sh1, char *net_name, char *r DEBUG(5,("make_srv_share_info1_str: %s %s\n", net_name, remark)); - make_unistr2(&(sh1->uni_netname), net_name, strlen(net_name)); - make_unistr2(&(sh1->uni_remark ), remark , strlen(remark )); + make_unistr2(&(sh1->uni_netname), net_name, strlen(net_name)+1); + make_unistr2(&(sh1->uni_remark ), remark , strlen(remark )+1); } /******************************************************************* @@ -103,8 +103,10 @@ static void make_srv_share_1_ctr(SHARE_INFO_1_CTR *ctr) } ctr->num_entries_read = num_entries; - ctr->ptr_share_info = num_entries > 0 ? 1 : 0; + ctr->ptr_share_info = num_entries > 0 ? 1 : 0; ctr->num_entries_read2 = num_entries; + ctr->num_entries_read3 = num_entries; + ctr->padding = 0; } /******************************************************************* diff --git a/source/srvparse.c b/source/srvparse.c index a94efff1384..8138285caf0 100644 --- a/source/srvparse.c +++ b/source/srvparse.c @@ -85,6 +85,8 @@ char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, in num_entries = MAX_SHARE_ENTRIES; /* report this! */ } + DBG_RW_IVAL("num_entries_read2", depth, base, io, q, ctr->num_entries_read2); q += 4; + for (i = 0; i < num_entries; i++) { q = srv_io_share_info1(io, &(ctr->info_1[i]), q, base, align, depth); @@ -95,7 +97,9 @@ char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, in q = srv_io_share_info1_str(io, &(ctr->info_1_str[i]), q, base, align, depth); } - DBG_RW_IVAL("num_entries_read2", depth, base, io, q, ctr->num_entries_read); q += 4; + q = align_offset(q, base, align); + DBG_RW_IVAL("num_entries_read3", depth, base, io, q, ctr->num_entries_read3); q += 4; + DBG_RW_IVAL("padding ", depth, base, io, q, ctr->padding); q += 4; } return q; -- cgit From 38c07fa932488542dbb687f8e0eca192d5f38a8e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 19 Oct 1997 23:22:03 +0000 Subject: update the timestamp on config files in our linked list when we notice they have changed, otherwise we keep reading them again and again --- source/param/loadparm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 1568e3abf51..9f47f14be5a 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -1425,10 +1425,10 @@ BOOL lp_file_list_changed(void) mod_time = file_modtime(n2); - if (f->modtime != mod_time) - { - DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); - return(True); + if (f->modtime != mod_time) { + DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); + f->modtime = mod_time; + return(True); } f = f->next; } -- cgit From 441b1697f091f8b0d56c05f77df9df98d5ebb640 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Sun, 19 Oct 1997 23:24:53 +0000 Subject: update the timestamp on config files in our linked list when we notice they have changed, otherwise we keep reading them again and again --- source/param/loadparm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 398a9050d6a..90a7c9a7276 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -1412,10 +1412,10 @@ BOOL lp_file_list_changed(void) mod_time = file_modtime(n2); - if (f->modtime != mod_time) - { - DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); - return(True); + if (f->modtime != mod_time) { + DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); + f->modtime = mod_time; + return(True); } f = f->next; } -- cgit From 9dfab27da3634539e99eb48c85dd5a64212e7005 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 20 Oct 1997 01:00:08 +0000 Subject: move calls to smbhash() inside smbdes.c (for legal reasons) --- source/include/proto.h | 7 +++++-- source/libsmb/credentials.c | 11 ++--------- source/libsmb/smbdes.c | 19 ++++++++++++++++++- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index aee8a86d05a..29252f16e37 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -834,9 +834,10 @@ BOOL smb_shm_get_usage(int *bytes_free, /*The following definitions come from smbdes.c */ void str_to_key(unsigned char *str,unsigned char *key); -void smbhash(unsigned char *out, unsigned char *in, unsigned char *key); void E_P16(unsigned char *p14,unsigned char *p16); void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); +void cred_hash1(char *out, char *in, char *key); +void cred_hash2(char *out, char *in, char *key); /*The following definitions come from smbencrypt.c */ @@ -889,9 +890,11 @@ struct smb_passwd *get_smbpwnam(char *name); /*The following definitions come from srvparse.c */ +char* srv_io_share_info1_str(BOOL io, SH_INFO_1_STR *sh1, char *q, char *base, int align, int depth); +char* srv_io_share_info1(BOOL io, SH_INFO_1 *sh1, char *q, char *base, int align, int depth); +char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, int align, int depth); char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth); char* srv_io_r_net_share_enum(BOOL io, SRV_R_NET_SHARE_ENUM *r_n, char *q, char *base, int align, int depth); -char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth); /*The following definitions come from status.c */ diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index 8881704a7a8..f1a41b0b3b6 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -35,7 +35,6 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, { uint32 sum[2]; char sum2[8]; - char buf[8]; char netsesskey[8]; sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); @@ -44,8 +43,7 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - smbhash(buf, sum2, pass); - smbhash(netsesskey, buf, pass+9); + cred_hash1(netsesskey, sum2, pass); session_key[0] = IVAL(netsesskey, 0); session_key[1] = IVAL(netsesskey, 4); @@ -74,8 +72,6 @@ Output: void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, DOM_CHAL *cred) { - char key2[7]; - char buf[8]; char calc_cred[8]; char timecred[8]; char netsesskey[8]; @@ -86,10 +82,7 @@ void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, SIVAL(timecred, 0, IVAL(stor_cred, 0) + timestamp.time); SIVAL(timecred, 4, IVAL(stor_cred, 4)); - smbhash(buf, timecred, netsesskey); - memset(key2, 0, 7); - key2[0] = netsesskey[7]; - smbhash(calc_cred, buf, key2); + cred_hash2(calc_cred, timecred, netsesskey); cred->data[0] = IVAL(calc_cred, 0); cred->data[1] = IVAL(calc_cred, 4); diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c index b62a160418d..90bad778c5a 100644 --- a/source/libsmb/smbdes.c +++ b/source/libsmb/smbdes.c @@ -275,7 +275,7 @@ void str_to_key(unsigned char *str,unsigned char *key) } -void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) +static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) { int i; char outb[64]; @@ -317,4 +317,21 @@ void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) smbhash(p24+16, c8, p21+14); } +void cred_hash1(char *out, char *in, char *key) +{ + char buf[8]; + + smbhash(buf, in, key); + smbhash(out, buf, key+9); +} + +void cred_hash2(char *out, char *in, char *key) +{ + char buf[8]; + static char key2[8]; + + smbhash(buf, in, key); + key2[0] = key[7]; + smbhash(out, buf, key2); +} -- cgit From 426cd6b2ded4725186a9262f13a327d8cf94364b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 20 Oct 1997 01:10:45 +0000 Subject: I am removing these from the source code in preparation for an upcoming 1.9.18alpha release. We can't release with this code in there as it currently stands as it might breach ITAR export restrictions in the US. I've discussed ways around this with Jeremy and we can put the code back in with appropriate modifications once it is needed. Note that this code isn't actually used in Samba yet, so removing it has no effect. If anyone wants the code then look in ~samba-bugs/arcfour/ or grab it from the CVS attic. --- source/arcfour.c | 91 -------------------------------------------------------- source/arcfour.h | 39 ------------------------ 2 files changed, 130 deletions(-) delete mode 100644 source/arcfour.c delete mode 100644 source/arcfour.h diff --git a/source/arcfour.c b/source/arcfour.c deleted file mode 100644 index a28d702a861..00000000000 --- a/source/arcfour.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a implementation of arcfour designed for use in the - SMB password change protocol based on the description - in 'Applied Cryptography', 2nd Edition. - - Copyright (C) Jeremy Allison 1997 - - 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 "arcfour.h" - -void set_arc4_key(unsigned char *data, int key_length, arc4_key *arckey) -{ - unsigned int i; - unsigned char j; - unsigned char tc; - unsigned char *s_box = &arckey->s_box[0]; - - arckey->index_i = 0; - arckey->index_j = 0; - for(i = 0; i < 256; i++) - s_box[i] = (unsigned char)i; - - j = 0; - for( i = 0; i < 256; i++) - { - j += (s_box[i] + data[i%key_length]); - tc = s_box[i]; - s_box[i] = s_box[j]; - s_box[j] = tc; - } -} - -void arc4(arc4_key *arckey, unsigned char *data_in, unsigned char *data_out, - int length) -{ - unsigned char tc; - int ind; - unsigned char i, j; - unsigned char t; - unsigned char *s_box = &arckey->s_box[0]; - - for( ind = 0; ind < length; ind++) - { - i = ++arckey->index_i; - j = arckey->index_j += s_box[i]; - tc = s_box[i]; - s_box[i] = s_box[j]; - s_box[j] = tc; - t = s_box[i] + s_box[j]; - *data_out++ = *data_in++ ^ s_box[t]; - } -} - -#if 0 -/* Test vector */ -unsigned char key_data[] = { 0x61, 0x8a, 0x63, 0xd2, 0xfb }; -unsigned char plaintext[] = { 0xdc, 0xee, 0x4c, 0xf9, 0x2c }; -unsigned char ciphertext[] = { 0xf1, 0x38, 0x29, 0xc9, 0xde }; - -int main(int argc, char *argv[]) -{ - unsigned char out[5]; - arc4_key key; - - set_arc4_key(key_data, 5, &key); - arc4(&key, plaintext, out, 5); - - if(memcmp(out, ciphertext, 5) ==0) - printf("Test ok !\n"); - else - printf("Test fail !\n"); - return 0; -} -#endif diff --git a/source/arcfour.h b/source/arcfour.h deleted file mode 100644 index 34a4e8f91be..00000000000 --- a/source/arcfour.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _ARC4_H_ -#define _ARC4_H_ - -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a implementation of arcfour designed for use in the - SMB password change protocol based on the description - in 'Applied Cryptography', 2nd Edition. - - Copyright (C) Jeremy Allison 1997 - - 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. -*/ - -typedef struct { - unsigned char s_box[256]; - unsigned char index_i; - unsigned char index_j; -} arc4_key; - -extern void set_arc4_key(unsigned char *data, int key_length, arc4_key *arckey); -extern void arc4(arc4_key *arckey, unsigned char *data_in, - unsigned char *data_out, int length); - -#endif /* _ARC4_H_ */ -- cgit From ab849a97821c9e1f199eea8ea2ec477687bed947 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 20 Oct 1997 02:50:12 +0000 Subject: casting cleanups --- source/include/proto.h | 7 +++---- source/lib/util.c | 3 ++- source/libsmb/credentials.c | 12 ++++++------ source/libsmb/smbdes.c | 12 ++++++------ source/smbd/password.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 29252f16e37..224aaa5a79c 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -833,11 +833,10 @@ BOOL smb_shm_get_usage(int *bytes_free, /*The following definitions come from smbdes.c */ -void str_to_key(unsigned char *str,unsigned char *key); void E_P16(unsigned char *p14,unsigned char *p16); void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); -void cred_hash1(char *out, char *in, char *key); -void cred_hash2(char *out, char *in, char *key); +void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key); +void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key); /*The following definitions come from smbencrypt.c */ @@ -1115,5 +1114,5 @@ void pstrcpy(char *dest, char *src); char *align4(char *q, char *base); char *align2(char *q, char *base); char *align_offset(char *q, char *base, int align_offset_len); -void dump_data(int level,unsigned char *buf,int len); +void dump_data(int level,char *buf1,int len); char *tab_depth(int depth); diff --git a/source/lib/util.c b/source/lib/util.c index 36e9e326acf..5c243204d02 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4414,8 +4414,9 @@ static void print_asc(int level, unsigned char *buf,int len) DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.')); } -void dump_data(int level,unsigned char *buf,int len) +void dump_data(int level,char *buf1,int len) { + unsigned char *buf = (unsigned char *)buf1; int i=0; if (len<=0) return; diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c index f1a41b0b3b6..ee7b1493e15 100644 --- a/source/libsmb/credentials.c +++ b/source/libsmb/credentials.c @@ -34,8 +34,8 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, uint32 session_key[2]) { uint32 sum[2]; - char sum2[8]; - char netsesskey[8]; + unsigned char sum2[8]; + unsigned char netsesskey[8]; sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); @@ -43,7 +43,7 @@ void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass, SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - cred_hash1(netsesskey, sum2, pass); + cred_hash1(netsesskey, sum2,(unsigned char *)pass); session_key[0] = IVAL(netsesskey, 0); session_key[1] = IVAL(netsesskey, 4); @@ -72,9 +72,9 @@ Output: void cred_create(uint32 session_key[2], DOM_CHAL *stor_cred, UTIME timestamp, DOM_CHAL *cred) { - char calc_cred[8]; - char timecred[8]; - char netsesskey[8]; + unsigned char calc_cred[8]; + unsigned char timecred[8]; + unsigned char netsesskey[8]; SIVAL(netsesskey, 0, session_key[0]); SIVAL(netsesskey, 4, session_key[1]); diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c index 90bad778c5a..67e27016c31 100644 --- a/source/libsmb/smbdes.c +++ b/source/libsmb/smbdes.c @@ -257,7 +257,7 @@ static void dohash(char *out, char *in, char *key) permute(out, rl, perm6, 64); } -void str_to_key(unsigned char *str,unsigned char *key) +static void str_to_key(unsigned char *str,unsigned char *key) { int i; @@ -317,18 +317,18 @@ void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) smbhash(p24+16, c8, p21+14); } -void cred_hash1(char *out, char *in, char *key) +void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key) { - char buf[8]; + unsigned char buf[8]; smbhash(buf, in, key); smbhash(out, buf, key+9); } -void cred_hash2(char *out, char *in, char *key) +void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key) { - char buf[8]; - static char key2[8]; + unsigned char buf[8]; + static unsigned char key2[8]; smbhash(buf, in, key); key2[0] = key[7]; diff --git a/source/smbd/password.c b/source/smbd/password.c index 9f4f0abcae8..2da8a8f9361 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1657,7 +1657,7 @@ BOOL server_cryptkey(char *buf) } /**************************************************************************** -attempted support for server level security +support for server level security ****************************************************************************/ BOOL server_validate(char *buf) { -- cgit From 65ab9adaa0d356b8041ed8a507ea52117f2a284e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Mon, 20 Oct 1997 08:46:00 +0000 Subject: a major share modes reorganisation. The shares modes code is now split into separate files. The shared memory implementation is in locking_shm.c. The slow implementation is in locking_slow.c It is all controlled by a struct share_ops structure that has function pointers to the implementation of all the functions needed by a share modes implementation. An initialisation function sets up this structure. This will make adding new implementations easy and clean. This also allowed me to get rid of the ugly code in smbstatus. Now status.c links to the locking code and calls methods in share_ops. I also renamed some things and generally organised things in a much cleaner fashion. Defines and structures specific to each implementation have been moved to the appropriate file and out of smb.h. --- source/include/proto.h | 39 +- source/include/smb.h | 69 +- source/locking/locking.c | 1458 ++--------------------------------------- source/locking/locking_shm.c | 739 +++++++++++++++++++++ source/locking/locking_slow.c | 1039 +++++++++++++++++++++++++++++ source/smbd/reply.c | 2 +- source/smbd/server.c | 30 +- source/utils/status.c | 311 ++------- 8 files changed, 1927 insertions(+), 1760 deletions(-) create mode 100644 source/locking/locking_shm.c create mode 100644 source/locking/locking_slow.c diff --git a/source/include/proto.h b/source/include/proto.h index 224aaa5a79c..024917a0d81 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -305,22 +305,25 @@ int lp_minor_announce_version(void); BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset); BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); -BOOL start_share_mode_mgmt(void); -BOOL stop_share_mode_mgmt(void); -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok); -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token); -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares); -void del_share_mode(share_lock_token token, int fnum); -BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type); -BOOL remove_share_oplock(int fnum, share_lock_token token); -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok); -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token); -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares); -void del_share_mode(share_lock_token token, int fnum); -BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type); -BOOL remove_share_oplock(int fnum, share_lock_token token); +BOOL locking_init(void); +BOOL locking_end(void); +BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok); +BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token); +int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **shares); +void del_share_mode(int token, int fnum); +BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type); +BOOL remove_share_oplock(int fnum, int token); +int share_mode_forall(void (*fn)(share_mode_entry *, char *)); +void share_status(FILE *f); + +/*The following definitions come from locking_shm.c */ + +struct share_ops *locking_shm_init(void); + +/*The following definitions come from locking_slow.c */ + +struct share_ops *locking_slow_init(void); /*The following definitions come from lsaparse.c */ @@ -778,7 +781,7 @@ BOOL check_name(char *name,int cnum); void sync_file(int fnum); void close_file(int fnum, BOOL normal_close); BOOL check_file_sharing(int cnum,char *fname); -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, +int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags); void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, int mode,int oplock_request, int *Access,int *action); @@ -791,7 +794,7 @@ int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line); int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line); int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line); BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval); -BOOL request_oplock_break(min_share_mode_entry *share_entry, +BOOL request_oplock_break(share_mode_entry *share_entry, uint32 dev, uint32 inode); BOOL snum_used(int snum); BOOL reload_services(BOOL test); diff --git a/source/include/smb.h b/source/include/smb.h index 0d10bd58954..ff6cc7eb25d 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -1195,29 +1195,6 @@ struct interface struct in_addr nmask; }; -/* share mode record pointed to in shared memory hash bucket */ -typedef struct -{ - smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */ - int locking_version; - int32 st_dev; - int32 st_ino; - int num_share_mode_entries; - smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */ - char file_name[1]; -} share_mode_record; - -/* share mode entry pointed to by share_mode_record struct */ -typedef struct -{ - smb_shm_offset_t next_share_mode_entry; - int pid; - uint16 op_port; - uint16 op_type; - int share_mode; - struct timeval time; -} share_mode_entry; - /* struct returned by get_share_modes */ typedef struct { @@ -1226,14 +1203,26 @@ typedef struct uint16 op_type; int share_mode; struct timeval time; -} min_share_mode_entry; +} share_mode_entry; -/* Token returned by lock_share_entry (actually ignored by FAST_SHARE_MODES code) */ -typedef int share_lock_token; /* Conversion to hash entry index from device and inode numbers. */ #define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size()) +/* each implementation of the share mode code needs + to support the following operations */ +struct share_ops { + BOOL (*stop_mgmt)(void); + BOOL (*lock_entry)(int , uint32 , uint32 , int *); + BOOL (*unlock_entry)(int , uint32 , uint32 , int ); + BOOL (*get_entries)(int , int , uint32 , uint32 , share_mode_entry **); + void (*del_entry)(int , int ); + BOOL (*set_entry)(int , int , uint16 , uint16 ); + BOOL (*remove_oplock)(int , int); + int (*forall)(void (*)(share_mode_entry *, char *)); + void (*status)(FILE *); +}; + /* this is used for smbstatus */ struct connect_record { @@ -1252,34 +1241,6 @@ struct connect_record #define LOCKING_VERSION 4 #endif /* LOCKING_VERSION */ -#if !defined(FAST_SHARE_MODES) -/* - * Defines for slow share modes. - */ - -/* - * Locking file header lengths & offsets. - */ -#define SMF_VERSION_OFFSET 0 -#define SMF_NUM_ENTRIES_OFFSET 4 -#define SMF_FILENAME_LEN_OFFSET 8 -#define SMF_HEADER_LENGTH 10 - -#define SMF_ENTRY_LENGTH 20 - -/* - * Share mode record offsets. - */ - -#define SME_SEC_OFFSET 0 -#define SME_USEC_OFFSET 4 -#define SME_SHAREMODE_OFFSET 8 -#define SME_PID_OFFSET 12 -#define SME_PORT_OFFSET 16 -#define SME_OPLOCK_TYPE_OFFSET 18 - -#endif /* FAST_SHARE_MODES */ - /* these are useful macros for checking validity of handles */ #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_OPEN_FILES)) #define OPEN_FNUM(fnum) (VALID_FNUM(fnum) && Files[fnum].open) diff --git a/source/locking/locking.c b/source/locking/locking.c index bbc0c0033ff..c75497c6b92 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -36,6 +36,8 @@ extern int DEBUGLEVEL; extern connection_struct Connections[]; extern files_struct Files[]; +static struct share_ops *share_ops; + /**************************************************************************** utility function called to see if a file region is locked ****************************************************************************/ @@ -104,1460 +106,102 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 * return True; /* Did unlock */ } -#ifdef FAST_SHARE_MODES -/******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ -BOOL start_share_mode_mgmt(void) -{ - pstring shmem_file_name; - - pstrcpy(shmem_file_name,lp_lockdir()); - if (!directory_exist(shmem_file_name,NULL)) - mkdir(shmem_file_name,0755); - trim_string(shmem_file_name,"","/"); - if (!*shmem_file_name) return(False); - strcat(shmem_file_name, "/SHARE_MEM_FILE"); - return smb_shm_open(shmem_file_name, lp_shmem_size()); -} -/******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ -BOOL stop_share_mode_mgmt(void) +/**************************************************************************** + initialise the locking functions +****************************************************************************/ +BOOL locking_init(void) { - return smb_shm_close(); -} +#ifdef FAST_SHARE_MODES + share_ops = locking_shm_init(); + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n")); + } + if (share_ops) return True; +#endif -/******************************************************************* - lock a hash bucket entry in shared memory for share_mode management - ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) -{ - return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); + share_ops = locking_slow_init(); + if (!share_ops) { + DEBUG(0,("ERROR: Failed to initialise share modes!\n")); + return False; + } + + return True; } /******************************************************************* - unlock a hash bucket entry in shared memory for share_mode management + deinitialize the share_mode management ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) +BOOL locking_end(void) { - return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); + return share_ops->stop_mgmt(); } -/******************************************************************* -get all share mode entries in shared memory for a dev/inode pair. -********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares) -{ - smb_shm_offset_t *mode_array; - unsigned int hash_entry = HASH_ENTRY(dev, inode); - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - int num_entries; - int num_entries_copied; - BOOL found = False; - min_share_mode_entry *share_array = (min_share_mode_entry *)0; - - *old_shares = 0; - - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return 0; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); - return 0; - } - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *)smb_shm_offset2addr( - file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \ -file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry)); - return (0); - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \ -record due to old locking version %d for file dev = %d, inode = %d in hash \ -bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - return (0); - } - - /* Allocate the old_shares array */ - num_entries = file_scanner_p->num_share_mode_entries; - if(num_entries) - { - *old_shares = share_array = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n")); - return 0; - } - } - - num_entries_copied = 0; - - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - int pid = entry_scanner_p->pid; - - if (pid && !process_exists(pid)) - { - /* Delete this share mode entry */ - share_mode_entry *delete_entry_p = entry_scanner_p; - int share_mode = entry_scanner_p->share_mode; - - if(entry_prev_p == entry_scanner_p) - { - /* We are at start of list */ - file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - } - else - { - entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; - entry_scanner_p = (share_mode_entry*) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - /* Decrement the number of share mode entries on this share mode record */ - file_scanner_p->num_share_mode_entries -= 1; - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return 0; - } - - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ -it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \ -bucket %d (number of entries now = %d)\n", - pid, share_mode, dev, inode, hash_entry, - file_scanner_p->num_share_mode_entries)); - - smb_shm_free(smb_shm_addr2offset(delete_entry_p)); - } - else - { - /* This is a valid share mode entry and the process that - created it still exists. Copy it into the output array. - */ - share_array[num_entries_copied].pid = entry_scanner_p->pid; - share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; - share_array[num_entries_copied].op_port = entry_scanner_p->op_port; - share_array[num_entries_copied].op_type = entry_scanner_p->op_type; - memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, - sizeof(struct timeval)); - num_entries_copied++; - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \ -record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid)); - entry_prev_p = entry_scanner_p; - entry_scanner_p = (share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - /* If no valid share mode entries were found then this record shouldn't exist ! */ - if(num_entries_copied == 0) - { - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ -hash bucket %d has a share mode record but no entries - deleting\n", - dev, inode, hash_entry)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - } - - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ -hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied)); - - return(num_entries_copied); -} /******************************************************************* -del the share mode of a file. -********************************************************************/ -void del_share_mode(share_lock_token token, int fnum) -{ - uint32 dev, inode; - smb_shm_offset_t *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - BOOL found = False; - int pid = getpid(); - - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", - hash_entry)); - return; - } - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \ -inode %d in hash bucket %d\n", dev, inode, hash_entry)); - return; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \ -record due to old locking version %d for file dev %d, inode %d hash bucket %d\n", - file_scanner_p->locking_version, dev, inode, hash_entry )); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - return; - } - - found = False; - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - if( (pid == entry_scanner_p->pid) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - if (found) - { - /* Decrement the number of entries in the record. */ - file_scanner_p->num_share_mode_entries -= 1; - - DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \ -Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n", - dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); - if(entry_prev_p == entry_scanner_p) - /* We are at start of list */ - file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; - else - entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; - smb_shm_free(smb_shm_addr2offset(entry_scanner_p)); - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return; - } - - /* If we deleted the last share mode entry then remove the share mode record. */ - if(file_scanner_p->num_share_mode_entries == 0) - { - DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \ -record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - } - } - else - { - DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \ -dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - } -} - -/******************************************************************* -set the share mode of a file. Return False on fail, True on success. -********************************************************************/ -BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type) -{ - files_struct *fs_p = &Files[fnum]; - int32 dev, inode; - smb_shm_offset_t *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *new_entry_p; - smb_shm_offset_t new_entry_offset; - BOOL found = False; - - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return False; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - /* We must create a share_mode_record */ - share_mode_record *new_mode_p = NULL; - smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) + - strlen(fs_p->name) + 1); - if(new_offset == NULL_OFFSET) - { - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n")); - return False; - } - new_mode_p = smb_shm_offset2addr(new_offset); - new_mode_p->locking_version = LOCKING_VERSION; - new_mode_p->st_dev = dev; - new_mode_p->st_ino = inode; - new_mode_p->num_share_mode_entries = 0; - new_mode_p->share_mode_entries = NULL_OFFSET; - strcpy(new_mode_p->file_name, fs_p->name); - - /* Chain onto the start of the hash chain (in the hope we will be used first). */ - new_mode_p->next_offset = mode_array[hash_entry]; - mode_array[hash_entry] = new_offset; - - file_scanner_p = new_mode_p; - - DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \ -inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); - } - - /* Now create the share mode entry */ - new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry)); - if(new_entry_offset == NULL_OFFSET) - { - smb_shm_offset_t delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n")); - /* Unlink the damaged record */ - mode_array[hash_entry] = file_scanner_p->next_offset; - /* And delete it */ - smb_shm_free( delete_offset ); - return False; - } - - new_entry_p = smb_shm_offset2addr(new_entry_offset); - - new_entry_p->pid = getpid(); - new_entry_p->share_mode = fs_p->share_mode; - new_entry_p->op_port = port; - new_entry_p->op_type = op_type; - memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); - - /* Chain onto the share_mode_record */ - new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries; - file_scanner_p->share_mode_entries = new_entry_offset; - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return False; - } - - /* Increment the share_mode_entries counter */ - file_scanner_p->num_share_mode_entries += 1; - - DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \ -0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid, - file_scanner_p->num_share_mode_entries)); - - return(True); -} - -/******************************************************************* -Remove an oplock port and mode entry from a share mode. -********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token token) -{ - uint32 dev, inode; - smb_shm_offset_t *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - BOOL found = False; - int pid = getpid(); - - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return False; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n", - hash_entry)); - return False; - } - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(0,("ERROR:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \ -inode %d in hash bucket %d\n", dev, inode, hash_entry)); - return False; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): Deleting old share mode \ -record due to old locking version %d for file dev %d, inode %d hash bucket %d\n", - file_scanner_p->locking_version, dev, inode, hash_entry )); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - return False; - } - - found = False; - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - if( (pid == entry_scanner_p->pid) && - (entry_scanner_p->share_mode == Files[fnum].share_mode) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - /* Delete the oplock info. */ - entry_scanner_p->op_port = 0; - entry_scanner_p->op_type = 0; - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - if(!found) - { - DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \ -mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - return False; - } - - return True; -} - -#else /* FAST_SHARE_MODES */ - -/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ - -/******************************************************************* - name a share file + lock a hash bucket entry ******************************************************************/ -static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) -{ - strcpy(name,lp_lockdir()); - standard_sub(cnum,name); - trim_string(name,"","/"); - if (!*name) return(False); - name += strlen(name); - - sprintf(name,"/share.%u.%u",dev,inode); - return(True); -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ - -static int delete_share_file( int cnum, char *fname ) +BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) { - /* the share file could be owned by anyone, so do this as root */ - become_root(False); - - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - else - { - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - } - - /* return to our previous privilage level */ - unbecome_root(False); - - return 0; + return share_ops->lock_entry(cnum, dev, inode, ptok); } /******************************************************************* - lock a share mode file. + unlock a hash bucket entry ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) +BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) { - pstring fname; - int fd; - int ret = True; - - *ptok = (share_lock_token)-1; - - if(!share_name(cnum, dev, inode, fname)) - return False; - - /* we need to do this as root */ - become_root(False); - - { - int old_umask; - BOOL gotlock = False; - old_umask = umask(0); - - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - struct stat dummy_stat; - -#ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); -#else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); -#endif /* SECURE_SHARE_MODES */ - - if(fd < 0) - { - DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", - fname, strerror(errno))); - ret = False; - break; - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - ret = False; - break; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - /* - * We have to come here if any of the above calls fail - * as we don't want to return and leave ourselves running - * as root ! - */ - - umask(old_umask); - } - - *ptok = (share_lock_token)fd; - - /* return to our previous privilage level */ - unbecome_root(False); - - return ret; + return share_ops->unlock_entry(cnum, dev, inode, token); } /******************************************************************* - unlock a share mode file. - ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) +get all share mode entries for a dev/inode pair. +********************************************************************/ +int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **shares) { - int fd = (int)token; - int ret = True; - struct stat sb; - pstring fname; - - /* Fix for zero length share files from - Gerald Werner <wernerg@mfldclin.edu> */ - - share_name(cnum, dev, inode, fname); - - /* get the share mode file size */ - if(fstat((int)token, &sb) != 0) - { - DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - sb.st_size = 1; - ret = False; - } - - /* If the file was zero length, we must delete before - doing the unlock to avoid a race condition (see - the code in lock_share_mode_entry for details. - */ - - /* remove the share file if zero length */ - if(sb.st_size == 0) - delete_share_file(cnum, fname); - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close(fd); - return ret; + return share_ops->get_entries(cnum, token, dev, inode, shares); } /******************************************************************* -Read a share file into a buffer. +del the share mode of a file. ********************************************************************/ - -static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +void del_share_mode(int token, int fnum) { - struct stat sb; - char *buf; - int size; - - *out = 0; - *p_new_file = False; - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); - return -1; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - *out = buf; - return 0; + share_ops->del_entry(token, fnum); } /******************************************************************* -get all share mode entries in a share file for a dev/inode pair. +set the share mode of a file. Return False on fail, True on success. ********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares) +BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type) { - int fd = (int)token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - min_share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by <n> share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - share_name(cnum, dev, inode, fname); - - if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return 0; - } - - if(num_entries) - { - *old_shares = share_array = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes: malloc fail !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - int pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = IVAL(p,SME_PID_OFFSET); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize)!= 0) - { - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; + return share_ops->set_entry(token, fnum, port, op_type); } /******************************************************************* -del a share mode from a share mode file. +Remove an oplock port and mode entry from a share mode. ********************************************************************/ -void del_share_mode(share_lock_token token, int fnum) +BOOL remove_share_oplock(int fnum, int token) { - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fs_p->cnum, fname); - return; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum,fname); - return; - } + return share_ops->remove_oplock(fnum, token); +} - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize) != 0) - { - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } -} - /******************************************************************* -set the share mode of a file +call the specified function on each entry under management by the +share mode system ********************************************************************/ -BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type) +int share_mode_forall(void (*fn)(share_mode_entry *, char *)) { - files_struct *fs_p = &Files[fnum]; - pstring fname; - int fd = (int)token; - int pid = (int)getpid(); - struct stat sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - int size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - sb.st_size + SMF_ENTRY_LENGTH)); - return False; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(SMF_HEADER_LENGTH + - strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); - strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); - SIVAL(p,SME_PID_OFFSET,pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fs_p->cnum, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) - { - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), - strerror(errno))); - if(buf) - free(buf); - return False; - } - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); - - return True; + return share_ops->forall(fn); } /******************************************************************* -Remove an oplock port and mode entry from a share mode. +dump the state of the system ********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token token) +void share_status(FILE *f) { - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL found = False; - BOOL new_file; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fs_p->cnum, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - remove the oplock settings on it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) - continue; - - DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - SSVAL(p,SME_PORT_OFFSET,0); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); - found = True; - break; - } - - if(!found) - { - DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; - + share_ops->status(f); } -#endif /* FAST_SHARE_MODES */ diff --git a/source/locking/locking_shm.c b/source/locking/locking_shm.c new file mode 100644 index 00000000000..99d981ed200 --- /dev/null +++ b/source/locking/locking_shm.c @@ -0,0 +1,739 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + shared memory locking implementation + Copyright (C) Andrew Tridgell 1992-1997 + + 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: + + 12 aug 96: Erik.Devriendt@te6.siemens.be + added support for shared memory implementation of share mode locking + + May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode + locking to deal with multiple share modes per open file. + + September 1997. Jeremy Allison (jallison@whistle.com). Added oplock + support. + + October 1997 - split into separate file (tridge) +*/ + +#ifdef FAST_SHARE_MODES + +#include "includes.h" +extern int DEBUGLEVEL; +extern connection_struct Connections[]; +extern files_struct Files[]; + +/* share mode record pointed to in shared memory hash bucket */ +typedef struct +{ + smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */ + int locking_version; + int32 st_dev; + int32 st_ino; + int num_share_mode_entries; + smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */ + char file_name[1]; +} share_mode_record; + +/* share mode entry pointed to by share_mode_record struct */ +typedef struct +{ + smb_shm_offset_t next_share_mode_entry; + share_mode_entry e; +} shm_share_mode_entry; + + +/******************************************************************* + deinitialize the shared memory for share_mode management + ******************************************************************/ +static BOOL shm_stop_share_mode_mgmt(void) +{ + return smb_shm_close(); +} + +/******************************************************************* + lock a hash bucket entry in shared memory for share_mode management + ******************************************************************/ +static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) +{ + return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); +} + +/******************************************************************* + unlock a hash bucket entry in shared memory for share_mode management + ******************************************************************/ +static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) +{ + return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); +} + +/******************************************************************* +get all share mode entries in shared memory for a dev/inode pair. +********************************************************************/ +static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **old_shares) +{ + smb_shm_offset_t *mode_array; + unsigned int hash_entry = HASH_ENTRY(dev, inode); + share_mode_record *file_scanner_p; + share_mode_record *file_prev_p; + shm_share_mode_entry *entry_scanner_p; + shm_share_mode_entry *entry_prev_p; + int num_entries; + int num_entries_copied; + BOOL found = False; + share_mode_entry *share_array = (share_mode_entry *)0; + + *old_shares = 0; + + if(hash_entry > lp_shmem_hash_size() ) + { + DEBUG(0, + ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \ +(max = %d)\n", + hash_entry, lp_shmem_hash_size() )); + return 0; + } + + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + if(mode_array[hash_entry] == NULL_OFFSET) + { + DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); + return 0; + } + + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_prev_p = file_scanner_p; + while(file_scanner_p) + { + if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) + { + found = True; + break; + } + else + { + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *)smb_shm_offset2addr( + file_scanner_p->next_offset); + } + } + + if(!found) + { + DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \ +file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry)); + return (0); + } + + if(file_scanner_p->locking_version != LOCKING_VERSION) + { + DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \ +record due to old locking version %d for file dev = %d, inode = %d in hash \ +bucket %d\n", file_scanner_p->locking_version, dev, inode, hash_entry)); + if(file_prev_p == file_scanner_p) + mode_array[hash_entry] = file_scanner_p->next_offset; + else + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); + return (0); + } + + /* Allocate the old_shares array */ + num_entries = file_scanner_p->num_share_mode_entries; + if(num_entries) + { + *old_shares = share_array = (share_mode_entry *) + malloc(num_entries * sizeof(share_mode_entry)); + if(*old_shares == 0) + { + DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n")); + return 0; + } + } + + num_entries_copied = 0; + + entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + file_scanner_p->share_mode_entries); + entry_prev_p = entry_scanner_p; + while(entry_scanner_p) + { + int pid = entry_scanner_p->e.pid; + + if (pid && !process_exists(pid)) + { + /* Delete this share mode entry */ + shm_share_mode_entry *delete_entry_p = entry_scanner_p; + int share_mode = entry_scanner_p->e.share_mode; + + if(entry_prev_p == entry_scanner_p) + { + /* We are at start of list */ + file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; + entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + file_scanner_p->share_mode_entries); + entry_prev_p = entry_scanner_p; + } + else + { + entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; + entry_scanner_p = (shm_share_mode_entry*) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } + /* Decrement the number of share mode entries on this share mode record */ + file_scanner_p->num_share_mode_entries -= 1; + + /* PARANOIA TEST */ + if(file_scanner_p->num_share_mode_entries < 0) + { + DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ +for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, + dev, inode, hash_entry)); + return 0; + } + + DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ +it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \ +bucket %d (number of entries now = %d)\n", + pid, share_mode, dev, inode, hash_entry, + file_scanner_p->num_share_mode_entries)); + + smb_shm_free(smb_shm_addr2offset(delete_entry_p)); + } + else + { + /* This is a valid share mode entry and the process that + created it still exists. Copy it into the output array. + */ + share_array[num_entries_copied].pid = entry_scanner_p->e.pid; + share_array[num_entries_copied].share_mode = entry_scanner_p->e.share_mode; + share_array[num_entries_copied].op_port = entry_scanner_p->e.op_port; + share_array[num_entries_copied].op_type = entry_scanner_p->e.op_type; + memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->e.time, + sizeof(struct timeval)); + num_entries_copied++; + DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \ +record mode 0x%X pid=%d\n", entry_scanner_p->e.share_mode, entry_scanner_p->e.pid)); + entry_prev_p = entry_scanner_p; + entry_scanner_p = (shm_share_mode_entry *) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } + } + + /* If no valid share mode entries were found then this record shouldn't exist ! */ + if(num_entries_copied == 0) + { + DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ +hash bucket %d has a share mode record but no entries - deleting\n", + dev, inode, hash_entry)); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + + if(file_prev_p == file_scanner_p) + mode_array[hash_entry] = file_scanner_p->next_offset; + else + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); + } + + DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ +hash bucket %d returning %d entries\n", dev, inode, hash_entry, num_entries_copied)); + + return(num_entries_copied); +} + +/******************************************************************* +del the share mode of a file. +********************************************************************/ +static void shm_del_share_mode(int token, int fnum) +{ + uint32 dev, inode; + smb_shm_offset_t *mode_array; + unsigned int hash_entry; + share_mode_record *file_scanner_p; + share_mode_record *file_prev_p; + shm_share_mode_entry *entry_scanner_p; + shm_share_mode_entry *entry_prev_p; + BOOL found = False; + int pid = getpid(); + + dev = Files[fnum].fd_ptr->dev; + inode = Files[fnum].fd_ptr->inode; + + hash_entry = HASH_ENTRY(dev, inode); + + if(hash_entry > lp_shmem_hash_size() ) + { + DEBUG(0, + ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ +(max = %d)\n", + hash_entry, lp_shmem_hash_size() )); + return; + } + + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + if(mode_array[hash_entry] == NULL_OFFSET) + { + DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", + hash_entry)); + return; + } + + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_prev_p = file_scanner_p; + + while(file_scanner_p) + { + if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) + { + found = True; + break; + } + else + { + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *) + smb_shm_offset2addr(file_scanner_p->next_offset); + } + } + + if(!found) + { + DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \ +inode %d in hash bucket %d\n", dev, inode, hash_entry)); + return; + } + + if(file_scanner_p->locking_version != LOCKING_VERSION) + { + DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \ +record due to old locking version %d for file dev %d, inode %d hash bucket %d\n", + file_scanner_p->locking_version, dev, inode, hash_entry )); + if(file_prev_p == file_scanner_p) + mode_array[hash_entry] = file_scanner_p->next_offset; + else + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); + return; + } + + found = False; + entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + file_scanner_p->share_mode_entries); + entry_prev_p = entry_scanner_p; + while(entry_scanner_p) + { + if( (pid == entry_scanner_p->e.pid) && + (memcmp(&entry_scanner_p->e.time, + &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + { + found = True; + break; + } + else + { + entry_prev_p = entry_scanner_p; + entry_scanner_p = (shm_share_mode_entry *) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } + } + + if (found) + { + /* Decrement the number of entries in the record. */ + file_scanner_p->num_share_mode_entries -= 1; + + DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \ +Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n", + dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); + if(entry_prev_p == entry_scanner_p) + /* We are at start of list */ + file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; + else + entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; + smb_shm_free(smb_shm_addr2offset(entry_scanner_p)); + + /* PARANOIA TEST */ + if(file_scanner_p->num_share_mode_entries < 0) + { + DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ +for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, + dev, inode, hash_entry)); + return; + } + + /* If we deleted the last share mode entry then remove the share mode record. */ + if(file_scanner_p->num_share_mode_entries == 0) + { + DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \ +record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); + if(file_prev_p == file_scanner_p) + mode_array[hash_entry] = file_scanner_p->next_offset; + else + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); + } + } + else + { + DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \ +dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); + } +} + +/******************************************************************* +set the share mode of a file. Return False on fail, True on success. +********************************************************************/ +static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type) +{ + files_struct *fs_p = &Files[fnum]; + int32 dev, inode; + smb_shm_offset_t *mode_array; + unsigned int hash_entry; + share_mode_record *file_scanner_p; + share_mode_record *file_prev_p; + shm_share_mode_entry *new_entry_p; + smb_shm_offset_t new_entry_offset; + BOOL found = False; + + dev = fs_p->fd_ptr->dev; + inode = fs_p->fd_ptr->inode; + + hash_entry = HASH_ENTRY(dev, inode); + if(hash_entry > lp_shmem_hash_size() ) + { + DEBUG(0, + ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ +(max = %d)\n", + hash_entry, lp_shmem_hash_size() )); + return False; + } + + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_prev_p = file_scanner_p; + + while(file_scanner_p) + { + if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) + { + found = True; + break; + } + else + { + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *) + smb_shm_offset2addr(file_scanner_p->next_offset); + } + } + + if(!found) + { + /* We must create a share_mode_record */ + share_mode_record *new_mode_p = NULL; + smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) + + strlen(fs_p->name) + 1); + if(new_offset == NULL_OFFSET) + { + DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n")); + return False; + } + new_mode_p = smb_shm_offset2addr(new_offset); + new_mode_p->locking_version = LOCKING_VERSION; + new_mode_p->st_dev = dev; + new_mode_p->st_ino = inode; + new_mode_p->num_share_mode_entries = 0; + new_mode_p->share_mode_entries = NULL_OFFSET; + strcpy(new_mode_p->file_name, fs_p->name); + + /* Chain onto the start of the hash chain (in the hope we will be used first). */ + new_mode_p->next_offset = mode_array[hash_entry]; + mode_array[hash_entry] = new_offset; + + file_scanner_p = new_mode_p; + + DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \ +inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); + } + + /* Now create the share mode entry */ + new_entry_offset = smb_shm_alloc( sizeof(shm_share_mode_entry)); + if(new_entry_offset == NULL_OFFSET) + { + smb_shm_offset_t delete_offset = mode_array[hash_entry]; + DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n")); + /* Unlink the damaged record */ + mode_array[hash_entry] = file_scanner_p->next_offset; + /* And delete it */ + smb_shm_free( delete_offset ); + return False; + } + + new_entry_p = smb_shm_offset2addr(new_entry_offset); + + new_entry_p->e.pid = getpid(); + new_entry_p->e.share_mode = fs_p->share_mode; + new_entry_p->e.op_port = port; + new_entry_p->e.op_type = op_type; + memcpy( (char *)&new_entry_p->e.time, (char *)&fs_p->open_time, sizeof(struct timeval)); + + /* Chain onto the share_mode_record */ + new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries; + file_scanner_p->share_mode_entries = new_entry_offset; + + /* PARANOIA TEST */ + if(file_scanner_p->num_share_mode_entries < 0) + { + DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ +for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, + dev, inode, hash_entry)); + return False; + } + + /* Increment the share_mode_entries counter */ + file_scanner_p->num_share_mode_entries += 1; + + DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \ +0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->e.pid, + file_scanner_p->num_share_mode_entries)); + + return(True); +} + +/******************************************************************* +Remove an oplock port and mode entry from a share mode. +********************************************************************/ +static BOOL shm_remove_share_oplock(int fnum, int token) +{ + uint32 dev, inode; + smb_shm_offset_t *mode_array; + unsigned int hash_entry; + share_mode_record *file_scanner_p; + share_mode_record *file_prev_p; + shm_share_mode_entry *entry_scanner_p; + shm_share_mode_entry *entry_prev_p; + BOOL found = False; + int pid = getpid(); + + dev = Files[fnum].fd_ptr->dev; + inode = Files[fnum].fd_ptr->inode; + + hash_entry = HASH_ENTRY(dev, inode); + + if(hash_entry > lp_shmem_hash_size() ) + { + DEBUG(0, + ("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash_entry %d too large \ +(max = %d)\n", + hash_entry, lp_shmem_hash_size() )); + return False; + } + + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + if(mode_array[hash_entry] == NULL_OFFSET) + { + DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n", + hash_entry)); + return False; + } + + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); + file_prev_p = file_scanner_p; + + while(file_scanner_p) + { + if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) + { + found = True; + break; + } + else + { + file_prev_p = file_scanner_p ; + file_scanner_p = (share_mode_record *) + smb_shm_offset2addr(file_scanner_p->next_offset); + } + } + + if(!found) + { + DEBUG(0,("ERROR:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \ +inode %d in hash bucket %d\n", dev, inode, hash_entry)); + return False; + } + + if(file_scanner_p->locking_version != LOCKING_VERSION) + { + DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): Deleting old share mode \ +record due to old locking version %d for file dev %d, inode %d hash bucket %d\n", + file_scanner_p->locking_version, dev, inode, hash_entry )); + if(file_prev_p == file_scanner_p) + mode_array[hash_entry] = file_scanner_p->next_offset; + else + file_prev_p->next_offset = file_scanner_p->next_offset; + smb_shm_free(smb_shm_addr2offset(file_scanner_p)); + return False; + } + + found = False; + entry_scanner_p = (shm_share_mode_entry*)smb_shm_offset2addr( + file_scanner_p->share_mode_entries); + entry_prev_p = entry_scanner_p; + while(entry_scanner_p) + { + if( (pid == entry_scanner_p->e.pid) && + (entry_scanner_p->e.share_mode == Files[fnum].share_mode) && + (memcmp(&entry_scanner_p->e.time, + &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) + { + /* Delete the oplock info. */ + entry_scanner_p->e.op_port = 0; + entry_scanner_p->e.op_type = 0; + found = True; + break; + } + else + { + entry_prev_p = entry_scanner_p; + entry_scanner_p = (shm_share_mode_entry *) + smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); + } + } + + if(!found) + { + DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \ +mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); + return False; + } + + return True; +} + + +/******************************************************************* +call the specified function on each entry under management by the +share ode system +********************************************************************/ +static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) +{ + int i, count=0; + smb_shm_offset_t *mode_array; + share_mode_record *file_scanner_p; + + mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); + + for( i = 0; i < lp_shmem_hash_size(); i++) { + smb_shm_lock_hash_entry(i); + if(mode_array[i] == NULL_OFFSET) { + smb_shm_unlock_hash_entry(i); + continue; + } + + file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]); + while((file_scanner_p != 0) && + (file_scanner_p->num_share_mode_entries != 0)) { + shm_share_mode_entry *entry_scanner_p = + (shm_share_mode_entry *) + smb_shm_offset2addr(file_scanner_p->share_mode_entries); + + while(entry_scanner_p != 0) { + + fn(&entry_scanner_p->e, + file_scanner_p->file_name); + + entry_scanner_p = + (shm_share_mode_entry *) + smb_shm_offset2addr( + entry_scanner_p->next_share_mode_entry); + count++; + } /* end while entry_scanner_p */ + file_scanner_p = (share_mode_record *) + smb_shm_offset2addr(file_scanner_p->next_offset); + } /* end while file_scanner_p */ + smb_shm_unlock_hash_entry(i); + } /* end for */ + + return count; +} + + +/******************************************************************* +dump the state of the system +********************************************************************/ +static void shm_share_status(FILE *f) +{ + int bytes_free, bytes_used, bytes_overhead, bytes_total; + + smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead); + bytes_total = bytes_free + bytes_used + bytes_overhead; + + fprintf(f, "Share mode memory usage (bytes):\n"); + fprintf(f, " %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n", + bytes_free, (bytes_free * 100)/bytes_total, + bytes_used, (bytes_used * 100)/bytes_total, + bytes_overhead, (bytes_overhead * 100)/bytes_total, + bytes_total); +} + + +static struct share_ops share_ops = { + shm_stop_share_mode_mgmt, + shm_lock_share_entry, + shm_unlock_share_entry, + shm_get_share_modes, + shm_del_share_mode, + shm_set_share_mode, + shm_remove_share_oplock, + shm_share_forall, + shm_share_status, +}; + +/******************************************************************* + initialize the shared memory for share_mode management + ******************************************************************/ +struct share_ops *locking_shm_init(void) +{ + pstring shmem_file_name; + + pstrcpy(shmem_file_name,lp_lockdir()); + if (!directory_exist(shmem_file_name,NULL)) + mkdir(shmem_file_name,0755); + trim_string(shmem_file_name,"","/"); + if (!*shmem_file_name) return(False); + strcat(shmem_file_name, "/SHARE_MEM_FILE"); + if (smb_shm_open(shmem_file_name, lp_shmem_size())) + return &share_ops; + return NULL; +} + +#else + int locking_shm_dummy_procedure(void) +{return 0;} +#endif + + + diff --git a/source/locking/locking_slow.c b/source/locking/locking_slow.c new file mode 100644 index 00000000000..cc646c6ca6d --- /dev/null +++ b/source/locking/locking_slow.c @@ -0,0 +1,1039 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + slow (lockfile) locking implementation + Copyright (C) Andrew Tridgell 1992-1997 + + 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: + + 12 aug 96: Erik.Devriendt@te6.siemens.be + added support for shared memory implementation of share mode locking + + May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode + locking to deal with multiple share modes per open file. + + September 1997. Jeremy Allison (jallison@whistle.com). Added oplock + support. + + October 1997 - split into separate file (tridge) +*/ + +#include "includes.h" +extern int DEBUGLEVEL; +extern connection_struct Connections[]; +extern files_struct Files[]; + +/* + * Locking file header lengths & offsets. + */ +#define SMF_VERSION_OFFSET 0 +#define SMF_NUM_ENTRIES_OFFSET 4 +#define SMF_FILENAME_LEN_OFFSET 8 +#define SMF_HEADER_LENGTH 10 + +#define SMF_ENTRY_LENGTH 20 + +/* + * Share mode record offsets. + */ + +#define SME_SEC_OFFSET 0 +#define SME_USEC_OFFSET 4 +#define SME_SHAREMODE_OFFSET 8 +#define SME_PID_OFFSET 12 +#define SME_PORT_OFFSET 16 +#define SME_OPLOCK_TYPE_OFFSET 18 + + +/******************************************************************* + deinitialize share_mode management + ******************************************************************/ +static BOOL slow_stop_share_mode_mgmt(void) +{ + return True; +} + + +/******************************************************************* + name a share file + ******************************************************************/ +static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) +{ + strcpy(name,lp_lockdir()); + trim_string(name,"","/"); + if (!*name) return(False); + name += strlen(name); + + sprintf(name,"/share.%u.%u",dev,inode); + return(True); +} + +/******************************************************************* +Force a share file to be deleted. +********************************************************************/ +static int delete_share_file( int cnum, char *fname ) +{ + /* the share file could be owned by anyone, so do this as root */ + become_root(False); + + if(unlink(fname) != 0) + { + DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", + fname, strerror(errno))); + } + else + { + DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); + } + + /* return to our previous privilage level */ + unbecome_root(False); + + return 0; +} + +/******************************************************************* + lock a share mode file. + ******************************************************************/ +static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok) +{ + pstring fname; + int fd; + int ret = True; + + *ptok = (int)-1; + + if(!share_name(cnum, dev, inode, fname)) + return False; + + /* we need to do this as root */ + become_root(False); + + { + int old_umask; + BOOL gotlock = False; + old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; + +#ifdef SECURE_SHARE_MODES + fd = (int)open(fname,O_RDWR|O_CREAT,0600); +#else /* SECURE_SHARE_MODES */ + fd = (int)open(fname,O_RDWR|O_CREAT,0666); +#endif /* SECURE_SHARE_MODES */ + + if(fd < 0) + { + DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n", + fname, strerror(errno))); + ret = False; + break; + } + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", + fname, strerror(errno))); + close(fd); + ret = False; + break; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + + /* + * We have to come here if any of the above calls fail + * as we don't want to return and leave ourselves running + * as root ! + */ + + umask(old_umask); + } + + *ptok = (int)fd; + + /* return to our previous privilage level */ + unbecome_root(False); + + return ret; +} + +/******************************************************************* + unlock a share mode file. + ******************************************************************/ +static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token) +{ + int fd = (int)token; + int ret = True; + struct stat sb; + pstring fname; + + /* Fix for zero length share files from + Gerald Werner <wernerg@mfldclin.edu> */ + + share_name(cnum, dev, inode, fname); + + /* get the share mode file size */ + if(fstat((int)token, &sb) != 0) + { + DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + sb.st_size = 1; + ret = False; + } + + /* If the file was zero length, we must delete before + doing the unlock to avoid a race condition (see + the code in lock_share_mode_entry for details. + */ + + /* remove the share file if zero length */ + if(sb.st_size == 0) + delete_share_file(cnum, fname); + + /* token is the fd of the open share mode file. */ + /* Unlock the first byte. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) + { + DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", + strerror(errno))); + ret = False; + } + + close(fd); + return ret; +} + +/******************************************************************* +Read a share file into a buffer. +********************************************************************/ +static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) +{ + struct stat sb; + char *buf; + int size; + + *out = 0; + *p_new_file = False; + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", + fname, strerror(errno))); + return -1; + } + + if(sb.st_size == 0) + { + *p_new_file = True; + return 0; + } + + /* Allocate space for the file */ + if((buf = (char *)malloc(sb.st_size)) == NULL) + { + DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); + return -1; + } + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ +for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } + + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return -1; + } + + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { + DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, + IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } + + /* Sanity check for file contents */ + size = sb.st_size; + size -= SMF_HEADER_LENGTH; /* Remove the header */ + + /* Remove the filename component. */ + size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); + + /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ + if((size % SMF_ENTRY_LENGTH) != 0) + { + DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return -1; + } + + *out = buf; + return 0; +} + +/******************************************************************* +get all share mode entries in a share file for a dev/inode pair. +********************************************************************/ +static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode, + share_mode_entry **old_shares) +{ + int fd = (int)token; + pstring fname; + int i; + int num_entries; + int num_entries_copied; + int newsize; + share_mode_entry *share_array; + char *buf = 0; + char *base = 0; + BOOL new_file; + + *old_shares = 0; + + /* Read the share file header - this is of the form: + 0 - locking version. + 4 - number of share mode entries. + 8 - 2 byte name length + [n bytes] file name (zero terminated). + + Followed by <n> share mode entries of the form : + + 0 - tv_sec + 4 - tv_usec + 8 - share_mode + 12 - pid + 16 - oplock port (if oplocks in use) - 2 bytes. + */ + + share_name(cnum, dev, inode, fname); + + if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", + fname)); + return 0; + } + + if(new_file == True) + return 0; + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return 0; + } + + if(num_entries) + { + *old_shares = share_array = (share_mode_entry *) + malloc(num_entries * sizeof(share_mode_entry)); + if(*old_shares == 0) + { + DEBUG(0,("get_share_modes: malloc fail !\n")); + return 0; + } + } + else + { + /* No entries - just delete the file. */ + DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } + + num_entries_copied = 0; + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for( i = 0; i < num_entries; i++) + { + int pid; + char *p = base + (i*SMF_ENTRY_LENGTH); + + pid = IVAL(p,SME_PID_OFFSET); + + if(!process_exists(pid)) + { + DEBUG(0,("get_share_modes: process %d no longer exists and \ +it left a share mode entry with mode 0x%X in share file %s\n", + pid, IVAL(p,SME_SHAREMODE_OFFSET), fname)); + continue; + } + share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); + share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); + share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); + share_array[num_entries_copied].pid = pid; + share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); + share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + + num_entries_copied++; + } + + if(num_entries_copied == 0) + { + /* Delete the whole file. */ + DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", + fname)); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + delete_share_file(cnum, fname); + return 0; + } + + /* If we deleted some entries we need to re-write the whole number of + share mode entries back into the file. */ + + if(num_entries_copied != num_entries) + { + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + + SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); + for( i = 0; i < num_entries_copied; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + SIVAL(p,SME_PID_OFFSET,share_array[i].pid); + SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); + SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); + SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); + } + + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize)!= 0) + { + DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(*old_shares) + free((char *)*old_shares); + *old_shares = 0; + if(buf) + free(buf); + return 0; + } + } + + if(buf) + free(buf); + + DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, + num_entries_copied)); + + return num_entries_copied; +} + +/******************************************************************* +del a share mode from a share mode file. +********************************************************************/ +static void slow_del_share_mode(int token, int fnum) +{ + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int newsize; + int i; + files_struct *fs_p = &Files[fnum]; + int pid; + BOOL deleted = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", + fname)); + return; + } + + if(new_file == True) + { + DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", + fname)); + delete_share_file(fs_p->cnum, fname); + return; + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return; + } + + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return; + } + + pid = getpid(); + + /* Go through the entries looking for the particular one + we have set - delete it. + */ + + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid)) + continue; + + DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", + i, num_entries, fname)); + + /* Remove this entry. */ + if(i != num_entries - 1) + memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); + + deleted = True; + break; + } + + if(!deleted) + { + DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return; + } + + num_entries--; + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries); + + if(num_entries == 0) + { + /* Deleted the last entry - remove the file. */ + DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum,fname); + return; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; + } + + newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); + if(write(fd, buf, newsize) != newsize) + { + DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return; + } + /* Now truncate the file at this point. */ + if(ftruncate(fd, newsize) != 0) + { + DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); + if(buf) + free(buf); + return; + } +} + +/******************************************************************* +set the share mode of a file +********************************************************************/ +static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type) +{ + files_struct *fs_p = &Files[fnum]; + pstring fname; + int fd = (int)token; + int pid = (int)getpid(); + struct stat sb; + char *buf; + int num_entries; + int header_size; + char *p; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(fstat(fd, &sb) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", + fname)); + return False; + } + + /* Sanity check for file contents (if it's not a new share file). */ + if(sb.st_size != 0) + { + int size = sb.st_size; + + /* Allocate space for the file plus one extra entry */ + if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL) + { + DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", + sb.st_size + SMF_ENTRY_LENGTH)); + return False; + } + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ +to 0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (read(fd,buf,sb.st_size) != sb.st_size) + { + DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", + fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) + { + DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ +locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), + LOCKING_VERSION)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ + + /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ + if((size % SMF_ENTRY_LENGTH) != 0) + { + DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ +deleting it.\n", fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + } + else + { + /* New file - just use a single_entry. */ + if((buf = (char *)malloc(SMF_HEADER_LENGTH + + strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) + { + DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); + return False; + } + SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); + SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); + strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); + SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); + SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); + SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); + SIVAL(p,SME_PID_OFFSET,pid); + SSVAL(p,SME_PORT_OFFSET,port); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); + + num_entries++; + + SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries); + + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ +0 for share file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) != + (header_size + (num_entries*SMF_ENTRY_LENGTH))) + { + DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ +deleting it (%s).\n",fname, strerror(errno))); + delete_share_file(fs_p->cnum, fname); + if(buf) + free(buf); + return False; + } + + /* Now truncate the file at this point - just for safety. */ + if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0) + { + DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ +mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries), + strerror(errno))); + if(buf) + free(buf); + return False; + } + + if(buf) + free(buf); + + DEBUG(3,("set_share_mode: Created share file %s with \ +mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); + + return True; +} + +/******************************************************************* +Remove an oplock port and mode entry from a share mode. +********************************************************************/ +static BOOL slow_remove_share_oplock(int fnum, int token) +{ + pstring fname; + int fd = (int)token; + char *buf = 0; + char *base = 0; + int num_entries; + int fsize; + int i; + files_struct *fs_p = &Files[fnum]; + int pid; + BOOL found = False; + BOOL new_file; + + share_name(fs_p->cnum, fs_p->fd_ptr->dev, + fs_p->fd_ptr->inode, fname); + + if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n", + fname)); + return False; + } + + if(new_file == True) + { + DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ +deleting it.\n", fname)); + delete_share_file(fs_p->cnum, fname); + return False; + } + + num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); + + DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", + fname, num_entries)); + + /* PARANOIA TEST */ + if(num_entries < 0) + { + DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ +for share file %d\n", num_entries, fname)); + return False; + } + + if(num_entries == 0) + { + /* No entries - just delete the file. */ + DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", + fname)); + if(buf) + free(buf); + delete_share_file(fs_p->cnum, fname); + return False; + } + + pid = getpid(); + + /* Go through the entries looking for the particular one + we have set - remove the oplock settings on it. + */ + + base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + + for(i = 0; i < num_entries; i++) + { + char *p = base + (i*SMF_ENTRY_LENGTH); + + if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || + (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || + (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || + (IVAL(p,SME_PID_OFFSET) != pid)) + continue; + + DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ +from the share file %s\n", i, num_entries, fname)); + + SSVAL(p,SME_PORT_OFFSET,0); + SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); + found = True; + break; + } + + if(!found) + { + DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); + if(buf) + free(buf); + return False; + } + + /* Re-write the file - and truncate it at the correct point. */ + if(lseek(fd, 0, SEEK_SET) != 0) + { + DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ +position 0 for share mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); + if(write(fd, buf, fsize) != fsize) + { + DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ +mode file %s (%s)\n", fname, strerror(errno))); + if(buf) + free(buf); + return False; + } + + return True; +} + + + +/******************************************************************* +call the specified function on each entry under management by the +share ode system +********************************************************************/ +static int slow_share_forall(void (*fn)(share_mode_entry *, char *)) +{ + int i, count=0; + void *dir; + char *s; + share_mode_entry e; + + dir = opendir(lp_lockdir()); + if (!dir) { + return(0); + } + + while ((s=readdirname(dir))) { + char *buf; + char *base; + int fd; + pstring lname; + uint32 dev,inode; + BOOL new_file; + pstring fname; + + if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue; + + strcpy(lname,lp_lockdir()); + trim_string(lname,NULL,"/"); + strcat(lname,"/"); + strcat(lname,s); + + fd = open(lname,O_RDWR,0); + if (fd < 0) { + continue; + } + + /* Lock the share mode file while we read it. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) { + close(fd); + continue; + } + + if(read_share_file( 0, fd, lname, &buf, &new_file)) { + close(fd); + continue; + } + strcpy( fname, &buf[10]); + close(fd); + + base = buf + SMF_HEADER_LENGTH + + SVAL(buf,SMF_FILENAME_LEN_OFFSET); + for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) { + char *p = base + (i*SMF_ENTRY_LENGTH); + e.pid = IVAL(p,SME_PID_OFFSET); + e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET); + e.time.tv_sec = IVAL(p,SME_SEC_OFFSET); + e.time.tv_usec = IVAL(p,SME_USEC_OFFSET); + e.op_port = SVAL(p,SME_PORT_OFFSET); + e.pid = SVAL(p,SME_PID_OFFSET); + e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); + + fn(&e, fname); + count++; + } /* end for i */ + + if(buf) + free(buf); + base = 0; + } /* end while */ + closedir(dir); + + return count; +} + + +/******************************************************************* +dump the state of the system +********************************************************************/ +static void slow_share_status(FILE *f) +{ + +} + + +static struct share_ops share_ops = { + slow_stop_share_mode_mgmt, + slow_lock_share_entry, + slow_unlock_share_entry, + slow_get_share_modes, + slow_del_share_mode, + slow_set_share_mode, + slow_remove_share_oplock, + slow_share_forall, + slow_share_status, +}; + +/******************************************************************* + initialize the slow share_mode management + ******************************************************************/ +struct share_ops *locking_slow_init(void) +{ + if (!directory_exist(lp_lockdir(),NULL)) { + mkdir(lp_lockdir(),0755); + if (!directory_exist(lp_lockdir(),NULL)) + return NULL; + } + + return &share_ops; +} diff --git a/source/smbd/reply.c b/source/smbd/reply.c index c5b7c500719..7576ee323b0 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -3422,7 +3422,7 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) (num_ulocks == 0) && (num_locks == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF)) { - share_lock_token token; + int token; files_struct *fsp = &Files[fnum]; uint32 dev = fsp->fd_ptr->dev; uint32 inode = fsp->fd_ptr->inode; diff --git a/source/smbd/server.c b/source/smbd/server.c index be24ad7781a..7d9638f01e8 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -1373,7 +1373,7 @@ void close_file(int fnum, BOOL normal_close) int cnum = fs_p->cnum; uint32 dev = fs_p->fd_ptr->dev; uint32 inode = fs_p->fd_ptr->inode; - share_lock_token token; + int token; invalidate_read_prediction(fs_p->fd_ptr->fd); fs_p->open = False; @@ -1477,10 +1477,10 @@ BOOL check_file_sharing(int cnum,char *fname) { int i; int ret = False; - min_share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = 0; int num_share_modes; struct stat sbuf; - share_lock_token token; + int token; int pid = getpid(); uint32 dev, inode; @@ -1509,7 +1509,7 @@ BOOL check_file_sharing(int cnum,char *fname) broke_oplock = False; for(i = 0; i < num_share_modes; i++) { - min_share_mode_entry *share_entry = &old_shares[i]; + share_mode_entry *share_entry = &old_shares[i]; /* * Break oplocks before checking share modes. See comment in @@ -1571,8 +1571,8 @@ free_and_exit: Helper for open_file_shared. Truncate a file after checking locking; close file if locked. **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, - BOOL *share_locked) +static void truncate_unless_locked(int fnum, int cnum, int token, + BOOL *share_locked) { if (Files[fnum].can_write){ if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ @@ -1596,7 +1596,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, /**************************************************************************** check if we can open a file with a share mode ****************************************************************************/ -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, +int check_share_mode( share_mode_entry *share, int deny_mode, char *fname, BOOL fcbopen, int *flags) { int old_open_mode = share->share_mode &0xF; @@ -1648,7 +1648,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, BOOL file_existed = file_exist(fname,&sbuf); BOOL share_locked = False; BOOL fcbopen = False; - share_lock_token token; + int token; uint32 dev = 0; uint32 inode = 0; int num_share_modes = 0; @@ -1724,7 +1724,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (lp_share_modes(SNUM(cnum))) { int i; - min_share_mode_entry *old_shares = 0; + share_mode_entry *old_shares = 0; if (file_existed) { @@ -1749,7 +1749,7 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, broke_oplock = False; for(i = 0; i < num_share_modes; i++) { - min_share_mode_entry *share_entry = &old_shares[i]; + share_mode_entry *share_entry = &old_shares[i]; /* * By observation of NetBench, oplocks are broken *before* share @@ -2794,7 +2794,7 @@ Send an oplock break message to another smbd process. If the oplock is held by the local smbd then call the oplock break function directly. ****************************************************************************/ -BOOL request_oplock_break(min_share_mode_entry *share_entry, +BOOL request_oplock_break(share_mode_entry *share_entry, uint32 dev, uint32 inode) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; @@ -4177,9 +4177,7 @@ void exit_server(char *reason) #endif } -#ifdef FAST_SHARE_MODES - stop_share_mode_mgmt(); -#endif /* FAST_SHARE_MODES */ + locking_end(); DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:"")); exit(0); @@ -5012,10 +5010,8 @@ static void usage(char *pname) if (!open_sockets(is_daemon,port)) exit(1); -#ifdef FAST_SHARE_MODES - if (!start_share_mode_mgmt()) + if (!locking_init()) exit(1); -#endif /* FAST_SHARE_MODES */ /* possibly reload the services file. */ reload_services(True); diff --git a/source/utils/status.c b/source/utils/status.c index 4143244ab4d..3e349f920a2 100644 --- a/source/utils/status.c +++ b/source/utils/status.c @@ -53,80 +53,52 @@ int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */ int Ucrit_MaxPid=0; /* added by OH */ unsigned int Ucrit_IsActive = 0; /* added by OH */ -#ifndef FAST_SHARE_MODES -static char *read_share_file(int fd, char *fname, char *progname) -{ - struct stat sb; - char *buf; - int size; - - if(fstat(fd, &sb) != 0) - { - printf("%s: ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - progname, fname, strerror(errno)); - return 0; - } - - if(sb.st_size == 0) - { - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) - { - printf("%s: read_share_file: malloc for file size %d fail !\n", - progname, (int)sb.st_size); - return 0; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - printf("%s: ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", progname, fname, strerror(errno)); - if(buf) - free(buf); - return 0; - } +/* we need these because we link to locking*.o */ + void become_root(BOOL save_dir) {} + void unbecome_root(BOOL restore_dir) {} +connection_struct Connections[MAX_CONNECTIONS]; +files_struct Files[MAX_OPEN_FILES]; - if (read(fd,buf,sb.st_size) != sb.st_size) - { - printf("%s: ERROR: read_share_file: Failed to read share file %s (%s)\n", - progname, fname, strerror(errno)); - if(buf) - free(buf); - return 0; - } - if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - printf("%s: ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - progname, IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION); - if(buf) - free(buf); - return 0; - } +static void print_share_mode(share_mode_entry *e, char *fname) +{ + static int count; + if (count==0) { + printf("Locked files:\n"); + printf("Pid DenyMode R/W Oplock Name\n"); + printf("--------------------------------------------------\n"); + } + count++; + + printf("%-5d ",e->pid); + switch ((e->share_mode>>4)&0xF) { + case DENY_NONE: printf("DENY_NONE "); break; + case DENY_ALL: printf("DENY_ALL "); break; + case DENY_DOS: printf("DENY_DOS "); break; + case DENY_READ: printf("DENY_READ "); break; + case DENY_WRITE:printf("DENY_WRITE "); break; + } + switch (e->share_mode&0xF) { + case 0: printf("RDONLY "); break; + case 1: printf("WRONLY "); break; + case 2: printf("RDWR "); break; + } + + if((e->op_type & + (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == + (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) + printf("EXCLUSIVE+BATCH "); + else if (e->op_type & EXCLUSIVE_OPLOCK) + printf("EXCLUSIVE "); + else if (e->op_type & BATCH_OPLOCK) + printf("BATCH "); + else + printf("NONE "); + + printf(" %s %s",fname,asctime(LocalTime((time_t *)&e->time.tv_sec))); +} - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 0) - { - printf("%s: ERROR: read_share_file: share file %s is an incorrect length.\n", - progname, fname); - if(buf) - free(buf); - return 0; - } - - return buf; -} -#endif /* FAST_SHARE_MODES */ int main(int argc, char *argv[]) { @@ -136,20 +108,8 @@ locking version (was %d, should be %d).\n",fname, static pstring servicesf = CONFIGFILE; extern char *optarg; int verbose = 0, brief =0; - BOOL firstopen=True; BOOL processes_only=False; int last_pid=0; -#ifdef FAST_SHARE_MODES - pstring shmem_file_name; - share_mode_record *file_scanner_p; - smb_shm_offset_t *mode_array; - int bytes_free, bytes_used, bytes_overhead, bytes_total; -#else /* FAST_SHARE_MODES */ - void *dir; - char *s; -#endif /* FAST_SHARE_MODES */ - int oplock_type; - int i; struct session_record *ptr; @@ -302,191 +262,16 @@ locking version (was %d, should be %d).\n",fname, printf("\n"); -#ifdef FAST_SHARE_MODES - /******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ - - strcpy(shmem_file_name,lp_lockdir()); - trim_string(shmem_file_name,"","/"); - if (!*shmem_file_name) exit(-1); - strcat(shmem_file_name, "/SHARE_MEM_FILE"); - if(!smb_shm_open(shmem_file_name, lp_shmem_size())) exit(-1); - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - if(mode_array == NULL) - { - printf("%s: base of shared memory hash array == 0! Exiting.\n", argv[0]); - smb_shm_close(); - exit(-1); - } - - for( i = 0; i < lp_shmem_hash_size(); i++) - { - smb_shm_lock_hash_entry(i); - if(mode_array[i] == NULL_OFFSET) - { - smb_shm_unlock_hash_entry(i); - continue; - } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]); - while((file_scanner_p != 0) && (file_scanner_p->num_share_mode_entries != 0)) - { - share_mode_entry *entry_scanner_p = - (share_mode_entry *)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - - while(entry_scanner_p != 0) - { - struct timeval t; - int pid = entry_scanner_p->pid; - int mode = entry_scanner_p->share_mode; - - t.tv_sec = entry_scanner_p->time.tv_sec; - t.tv_usec = entry_scanner_p->time.tv_usec; - strcpy(fname, file_scanner_p->file_name); - oplock_type = entry_scanner_p->op_type; - -#else /* FAST_SHARE_MODES */ - - /* For slow share modes go through all the files in - the share mode directory and read the entries in - each. - */ - - dir = opendir(lp_lockdir()); - if (!dir) - { - printf("%s: Unable to open lock directory %s.\n", argv[0], lp_lockdir()); - return(0); - } - while ((s=readdirname(dir))) { - char *buf; - char *base; - int fd; - pstring lname; - uint32 dev,inode; - - if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue; - - strcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - strcat(lname,"/"); - strcat(lname,s); - - fd = open(lname,O_RDWR,0); - if (fd < 0) - { - printf("%s: Unable to open share file %s.\n", argv[0], lname); - continue; - } - - /* Lock the share mode file while we read it. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - printf("%s: Unable to lock open share file %s.\n", argv[0], lname); - close(fd); - continue; - } - - if(( buf = read_share_file( fd, lname, argv[0] )) == NULL) - { - close(fd); - continue; - } - strcpy( fname, &buf[10]); - close(fd); - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - struct timeval t; - int pid = IVAL(p,SME_PID_OFFSET); - int mode = IVAL(p,SME_SHAREMODE_OFFSET); - - t.tv_sec = IVAL(p,SME_SEC_OFFSET); - t.tv_usec = IVAL(p,SME_USEC_OFFSET); - oplock_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); -#endif /* FAST_SHARE_MODES */ - - fname[sizeof(fname)-1] = 0; - - if (firstopen) { - firstopen=False; - printf("Locked files:\n"); - printf("Pid DenyMode R/W Oplock Name\n"); - printf("--------------------------------------------------\n"); - } - - - printf("%-5d ",pid); - switch ((mode>>4)&0xF) - { - case DENY_NONE: printf("DENY_NONE "); break; - case DENY_ALL: printf("DENY_ALL "); break; - case DENY_DOS: printf("DENY_DOS "); break; - case DENY_READ: printf("DENY_READ "); break; - case DENY_WRITE:printf("DENY_WRITE "); break; - } - switch (mode&0xF) - { - case 0: printf("RDONLY "); break; - case 1: printf("WRONLY "); break; - case 2: printf("RDWR "); break; - } - - if((oplock_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - printf("EXCLUSIVE+BATCH "); - else if (oplock_type & EXCLUSIVE_OPLOCK) - printf("EXCLUSIVE "); - else if (oplock_type & BATCH_OPLOCK) - printf("BATCH "); - else - printf("NONE "); - - printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec))); - -#ifdef FAST_SHARE_MODES + locking_init(); - entry_scanner_p = (share_mode_entry *)smb_shm_offset2addr( - entry_scanner_p->next_share_mode_entry); - } /* end while entry_scanner_p */ - file_scanner_p = (share_mode_record *)smb_shm_offset2addr( - file_scanner_p->next_offset); - } /* end while file_scanner_p */ - smb_shm_unlock_hash_entry(i); - } /* end for */ - - smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead); - bytes_total = bytes_free + bytes_used + bytes_overhead; - - /******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ - smb_shm_close(); + if (share_mode_forall(print_share_mode) <= 0) + printf("No locked files\n"); -#else /* FAST_SHARE_MODES */ - } /* end for i */ + printf("\n"); - if(buf) - free(buf); - base = 0; - } /* end while */ - closedir(dir); + share_status(stdout); -#endif /* FAST_SHARE_MODES */ - if (firstopen) - printf("No locked files\n"); -#ifdef FAST_SHARE_MODES - printf("\nShare mode memory usage (bytes):\n"); - printf(" %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n", - bytes_free, (bytes_free * 100)/bytes_total, - bytes_used, (bytes_used * 100)/bytes_total, - bytes_overhead, (bytes_overhead * 100)/bytes_total, - bytes_total); - -#endif /* FAST_SHARE_MODES */ + locking_end(); return (0); } -- cgit From 53a8a6ced58429886fef019a56c9059e0dcb6622 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Mon, 20 Oct 1997 10:30:15 +0000 Subject: Fixed Upper/Lower case typos. --- docs/textdocs/WinNT.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/textdocs/WinNT.txt b/docs/textdocs/WinNT.txt index d85f9966bc7..54431d88690 100644 --- a/docs/textdocs/WinNT.txt +++ b/docs/textdocs/WinNT.txt @@ -29,7 +29,7 @@ The following registry entry change will re-enable clear text password handling: Run regedt32.exe and locate the hive key entry: -HKEY_LOCAL_MACHINE\system\CurrentControlSet\Services\rdr\parameters\ +HKEY_LOCAL_MACHINE\system\CurrentControlSet\Services\Rdr\Parameters\ Add the following value: EnablePlainTextPassword:REG_DWORD=1 -- cgit From c6c28a4c3c9010ff9d5eac4bad091189a786d5a0 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 12:10:58 +0000 Subject: util.c password.c : added automount_server() function which, if -DAUTOMOUNT is in use, returns the server name of the NIS auto.map entry. otherwise, it returns local_server. added use of automount_server() for a new substitution %N for NIS home server. this defaults, via automount_server(), to the same functionality as %L if -DAUTOMOUNT is not used. removed vuser->home_share. moved code that grabbed the servername into the separate function automount_server(). loadparm.c : created "logon drive" (default of "") created "logon home" (default of "\\%N\%U") changed default of "logon path" from NULL to "\\%N\%U\profile". ipc.c pipenetlog.c : use lp_logon_drive(), lp_logon_home() and lp_logon_path() in their now easier-to-use form (don't have to check if *lp_logon_path() and manually substitute a default of \\%L\%U and do a standard_sub_basic() on the result, because the default automatically does this. --- source/include/proto.h | 3 +++ source/lib/util.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ source/param/loadparm.c | 11 ++++++++++ source/pipenetlog.c | 19 +++++------------ source/smbd/ipc.c | 31 ++-------------------------- source/smbd/password.c | 35 -------------------------------- 6 files changed, 75 insertions(+), 78 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 024917a0d81..e12ea4002d7 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -155,6 +155,8 @@ char *lp_username_map(void); char *lp_character_set(void); char *lp_logon_script(void); char *lp_logon_path(void); +char *lp_logon_drive(void); +char *lp_logon_home(void); char *lp_remote_announce(void); char *lp_wins_server(void); char *lp_interfaces(void); @@ -1088,6 +1090,7 @@ BOOL zero_ip(struct in_addr ip); void reset_globals_after_fork(); char *client_name(void); char *client_addr(void); +char *automount_server(char *username); void standard_sub_basic(char *str); BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); int PutUniCode(char *dst,char *src); diff --git a/source/lib/util.c b/source/lib/util.c index 5c243204d02..9295d9ae73f 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -21,6 +21,10 @@ #include "includes.h" +#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#include "rpcsvc/ypclnt.h" +#endif + pstring scope = ""; int DEBUGLEVEL = 1; @@ -3602,6 +3606,55 @@ char *client_addr(void) return addr_buf; } +char *automount_server(char *user_name) +{ + static pstring server_name; + +#if (defined(NETGROUP) && defined (AUTOMOUNT)) + int nis_error; /* returned by yp all functions */ + char *nis_result; /* yp_match inits this */ + int nis_result_len; /* and set this */ + char *nis_domain; /* yp_get_default_domain inits this */ + char *nis_map = (char *)lp_nis_home_map_name(); + int home_server_len; + + /* set to default of no string */ + server_name[0] = 0; + + if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) + { + DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); + } + + DEBUG(5, ("NIS Domain: %s\n", nis_domain)); + + if ((nis_error = yp_match(nis_domain, nis_map, + user_name, strlen(user_name), + &nis_result, &nis_result_len)) != 0) + { + DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); + } + + if (!nis_error && lp_nis_home_map()) + { + home_server_len = strcspn(nis_result,":"); + DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len)); + if (home_server_len > sizeof(pstring)) + { + home_server_len = sizeof(pstring); + } + strncpy(server_name, nis_result, home_server_len); + } +#else + /* use the local machine name instead of the auto-map server */ + pstrcpy(server_name, local_machine); +#endif + + DEBUG(4,("Home server: %s\n", server_name)); + + return server_name; +} + /******************************************************************* sub strings with useful parameters Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and @@ -3630,6 +3683,7 @@ void standard_sub_basic(char *str) } break; } + case 'N' : string_sub(p,"%N", automount_server(username)); break; case 'I' : string_sub(p,"%I", client_addr()); break; case 'L' : string_sub(p,"%L", local_machine); break; case 'M' : string_sub(p,"%M", client_name()); break; diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 9f47f14be5a..9a268193978 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -132,6 +132,8 @@ typedef struct char *szCharacterSet; char *szLogonScript; char *szLogonPath; + char *szLogonDrive; + char *szLogonHome; char *szSmbrun; char *szWINSserver; char *szInterfaces; @@ -445,6 +447,8 @@ struct parm_struct {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set}, {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL}, {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL}, + {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL}, + {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL}, {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL}, {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL}, {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL}, @@ -620,6 +624,11 @@ static void init_globals(void) string_set(&Globals.szServerString,s); sprintf(s,"%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); string_set(&Globals.szAnnounceVersion,s); + + string_set(&Globals.szLogonDrive, ""); + /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */ + string_set(&Globals.szLogonHome, "\\\\%N\\%U"); + string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile"); Globals.bLoadPrinters = True; Globals.bUseRhosts = False; Globals.max_packet = 65535; @@ -838,6 +847,8 @@ FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap) FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet) FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) +FN_GLOBAL_STRING(lp_logon_drive,&Globals.szLogonDrive) +FN_GLOBAL_STRING(lp_logon_home,&Globals.szLogonHome) FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver) FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index 0dac8048346..d407e006610 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -524,20 +524,14 @@ static void api_lsa_sam_logon( user_struct *vuser, pstrcpy(dom_sid , lp_domainsid ()); pstrcpy(my_workgroup, lp_workgroup ()); - pstrcpy(my_name , myname ); - strupper(my_name); - - pstrcpy(home_drive , "a:" ); - -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - pstrcpy(home_dir , vuser->home_share); -#else - pstrcpy(home_dir , "\\\\%L\\%U"); -#endif - standard_sub_basic(home_dir); + pstrcpy(home_drive , lp_logon_drive ()); + pstrcpy(home_dir , lp_logon_home ()); sam_logon_in_ssb = False; + pstrcpy(my_name , myname ); + strupper(my_name); + make_lsa_user_info(&usr_info, &dummy_time, /* logon_time */ @@ -603,9 +597,6 @@ BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, if ((vuser = get_valid_user_struct(uid)) == NULL) return False; DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if defined(NETGROUP) && defined(AUTOMOUNT) - DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif switch (opnum) { diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 142f139d260..466781c58c8 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1999,9 +1999,6 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* get NIS home of a previously validated user - simeon */ user_struct *vuser = get_valid_user_struct(vuid); DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2059,19 +2056,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ SIVALS(p,usri11_password_age,0xffffffff); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); + strcpy(p2, lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ strcpy(p2,""); @@ -2107,19 +2092,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, SSVAL(p,42, Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); + strcpy(p2,lp_logon_path()); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; diff --git a/source/smbd/password.c b/source/smbd/password.c index 2da8a8f9361..311ef47679f 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -155,15 +155,6 @@ tell random client vuid's (normally zero) from valid vuids. uint16 register_vuid(int uid,int gid, char *name,BOOL guest) { user_struct *vuser; - -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - int nis_error; /* returned by yp all functions */ - char *nis_result; /* yp_match inits this */ - int nis_result_len; /* and set this */ - char *nis_domain; /* yp_get_default_domain inits this */ - char *nis_map = (char *)lp_nis_home_map_name(); - int home_server_len; -#endif struct passwd *pwfile; /* for getting real name from passwd file */ #if 0 @@ -224,32 +215,6 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest) DEBUG(3,("uid %d registered to name %s\n",uid,name)); -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - vuser->home_share = NULL; - DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); - vuser->home_share = Realloc(vuser->home_share, 32); - strcpy(vuser->home_share,"\\\\%L\\%U"); - - if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - DEBUG(3, ("NIS Domain: %s\n", nis_domain)); - - if ((nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), - &nis_result, &nis_result_len)) != 0) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - if (!nis_error && lp_nis_home_map()) { - home_server_len = strcspn(nis_result,":"); - DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len)); - vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12); - DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 )); - strcpy(vuser->home_share,"\\\\"); - strncat(vuser->home_share, nis_result, home_server_len); - strcat(vuser->home_share,"\\homes"); - DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n", - vuser->name, vuser->uid, nis_result, vuser->home_share)); - } -#endif - DEBUG(3, ("Clearing default real name\n")); fstrcpy(vuser->real_name, "<Full Name>\0"); if (lp_unix_realname()) { -- cgit From c59b8cee4721eeeb79f07f48ac17492530d4cdb1 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 12:13:04 +0000 Subject: removed home_share from user_info structure. --- source/include/smb.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/include/smb.h b/source/include/smb.h index ff6cc7eb25d..2b0fc44d244 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -1141,10 +1141,6 @@ typedef struct int *igroups; /* an integer version - some OSes are broken :-( */ int *attrs; /* attributes associated with each gid */ -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - char *home_share; /* to store NIS home of a user - simeon */ -#endif - int n_sids; int *sids; -- cgit From 9dc6fa1869b5be3c3032b6f7a1b3195292927040 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 13:00:55 +0000 Subject: updated briefly to mention NT domain support as working, but experimental. --- docs/textdocs/DOMAIN.txt | 72 +++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/docs/textdocs/DOMAIN.txt b/docs/textdocs/DOMAIN.txt index 3cd8a125b7b..0f5ea49c3dd 100644 --- a/docs/textdocs/DOMAIN.txt +++ b/docs/textdocs/DOMAIN.txt @@ -41,21 +41,29 @@ cannot be implemented with an underlying username database which is different from the Windows NT SAM. Support for the Remote Administration Protocol is planned for a future release of Samba. -The domain support works for WfWg, and Win95 clients. Support for Windows -NT and OS/2 clients is still being worked on and is still experimental. -Support for profiles is confirmed as working for Win95, NT 4.0 and NT 3.51, -although NT Workstation requires manual configuration of user accounts with -NT's "User Manager for Domains", and no automatic profile location support -is available using samba, although it has been confirmed as possible to use -an NT server to specify that the location of profiles is on a samba server. - -The help of an NT server can be enlisted, both for profile storage and -for user authentication. For details on user authentication, see +The domain support works for WfWg, and Win95 clients and NT 4.0 and 3.51. +Domain support is currently at an early experimental stage for NT 4.0 and +NT 3.51. Support for Windows OS/2 clients is still being worked on and is +still experimental. + +Support for profiles is confirmed as working for Win95, NT 4.0 and NT 3.51. +It is possible to specify: the profile location; script file to be loaded +on login; the user's home directory; and for NT a kick-off time could also +now easily be supported. + +With NT Workstations, all this does not require the use or intervention of +an NT 4.0 or NT 3.51 server: Samba can now replace the logon services +provided by an NT server, to a limited and experimental degree (for example, +running "User Manager for Domains" will not provide you with access to +a domain created by a Samba Server). + +With Win95, the help of an NT server can be enlisted, both for profile storage +and for user authentication. For details on user authentication, see security_level.txt. For details on profile storage, see below. Using these features you can make your clients verify their logon via -the Samba server, make clients run a batch file when they logon to +the Samba server; make clients run a batch file when they logon to the network and download their preferences, desktop and start menu. @@ -70,9 +78,7 @@ To use domain logons and profiles you need to do the following: for details. 2) Setup a WINS server (see NetBIOS.txt) and configure all your clients - to use that WINS service. [lkcl 12jul97 - problems occur where - clients do not pick up the profiles properly unless they are using a - WINS server. this is still under investigation]. + to use that WINS service. 3) Create a share called [netlogon] in your smb.conf. This share should be readable by all users, and probably should not be writeable. This @@ -136,8 +142,8 @@ In the [global] section of smb.conf set the following (for example): logon path = \\profileserver\profileshare\profilepath\%U\moreprofilepath -The default for this option is \\%L\%U\profile, namely -\\sambaserver\username\profile. The \\L%\%U services is created +The default for this option is \\%N\%U\profile, namely +\\sambaserver\username\profile. The \\N%\%U service is created automatically by the [homes] service. If you are using a samba server for the profiles, you _must_ make the @@ -270,15 +276,18 @@ Windows NT Workstation 4.0 -------------------------- When a user first logs in to a Windows NT Workstation, the profile -NTuser.MAN is created. The "User Manager for Domains" can be used -to specify the location of the profile. Samba cannot be a domain -logon server for NT, therefore you will need to manually configure -each and every account. [lkcl 10aug97 - i tried setting the path -in each account to \\samba-server\homes\profile, and discovered that -this fails because a background process maintains the connection to -the [homes] share which does _not_ close down in between user logins. -you have to have \\samba-server\user\profile, where user is the -username created from the [homes] share]. +NTuser.DAT is created. The profile location can be now specified +through the "logon path" parameter, in exactly the same way as it +can for Win95. [lkcl 10aug97 - i tried setting the path to +\\samba-server\homes\profile, and discovered that this fails because +a background process maintains the connection to the [homes] share +which does _not_ close down in between user logins. you have to +have \\samba-server\%L\profile, where user is the username created +from the [homes] share]. + +There is a parameter that is now available for use with NT Profiles: +"logon drive". This should be set to "h:" or any other drive, and +should be used in conjunction with the new "logon home" parameter. The entry for the NT 4.0 profile is a _directory_ not a file. The NT help on profiles mentions that a directory is also created with a .PDS @@ -326,18 +335,17 @@ a mandatory profile, NTuser.MAN]. Windows NT Server ----------------- -Following the instructions for NT Workstation, there is nothing to stop -you specifying any path that you like for the location of users' profiles. -Therefore, you could specify that the profile be stored on a samba server, -or any other SMB server, as long as that SMB server supports encrypted -passwords. +There is nothing to stop you specifying any path that you like for the +location of users' profiles. Therefore, you could specify that the +profile be stored on a samba server, or any other SMB server, as long as +that SMB server supports encrypted passwords. Sharing Profiles between W95 and NT Workstation 4.0 --------------------------------------------------- -The default logon path is \\%L\U%. NT Workstation will attempt to create +The default logon path is \\%N\U%. NT Workstation will attempt to create a directory "\\samba-server\username.PDS" if you specify the logon path as "\\samba-server\username" with the NT User Manager. Therefore, you will need to specify (for example) "\\samba-server\username\profile". @@ -348,7 +356,7 @@ If you then want to share the same Start Menu / Desktop with W95, you will need to specify "logon path = \\samba-server\username\profile" [lkcl 10aug97 this has its drawbacks: i created a shortcut to telnet.exe, which attempts to run from the c:\winnt\system32 directory. this directory is obviously -unlikely to exist on a W95 host]. +unlikely to exist on a Win95-only host]. If you have this set up correctly, you will find separate user.DAT and NTuser.DAT files in the same profile directory. -- cgit From 82318e300b34b5a0897acdba035eac8e5a08b7fc Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Mon, 20 Oct 1997 13:14:20 +0000 Subject: Updated with DNS Proxy, Printing and [netlogon] share modes = no --- examples/smb.conf.default | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 9664ac1ab47..b8895bd4cf6 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -27,11 +27,16 @@ # the smb.conf man page ; hosts allow = 192.168.1. 192.168.2. 127. -# if you want to automatically load your printer list rather +# If you want to automatically load your printer list rather # than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes +# It should not be necessary to spell out the print system type unless +# yours is non-standard. Currently supported print systems include: +# bsd, sysv, plp, lprng, aix, hpux, qnx +; printing = bsd + # Uncomment this if you want a guest account, you must add this to /etc/passwd # otherwise the user "nobody" is used ; guest account = pcguest @@ -119,6 +124,11 @@ # at least one WINS Server on the network. The default is NO. ; wins proxy = yes +# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names +# via DNS nslookups. The built-in default for versions 1.9.17 is yes, +# this has been changed in version 1.9.18 to no. + dns proxy = no + #============================ Share Definitions ============================== [homes] comment = Home Directories @@ -131,6 +141,7 @@ ; path = /usr/local/samba/lib/netlogon ; guest ok = yes ; writable = no +; share modes = no # Un-comment the following to provide a specific roving profile share -- cgit From 7b3340c78dd9654d6f8e04196be6cd9e826daaf6 Mon Sep 17 00:00:00 2001 From: John Terpstra <jht@samba.org> Date: Mon, 20 Oct 1997 13:18:16 +0000 Subject: Added DNS Proxy, Printing, [netlogon] share modes = no. --- examples/smb.conf.default | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/smb.conf.default b/examples/smb.conf.default index 9664ac1ab47..a827050e9e3 100644 --- a/examples/smb.conf.default +++ b/examples/smb.conf.default @@ -27,11 +27,16 @@ # the smb.conf man page ; hosts allow = 192.168.1. 192.168.2. 127. -# if you want to automatically load your printer list rather +# If you want to automatically load your printer list rather # than setting them up individually then you'll need this printcap name = /etc/printcap load printers = yes +# It should not be necessary to specify the print system type unless +# it is non-standard. Currently supported print systems include: +# bsd, sysv, plp, lprng, aix, hpux, qnx +; printing = bsd + # Uncomment this if you want a guest account, you must add this to /etc/passwd # otherwise the user "nobody" is used ; guest account = pcguest @@ -119,6 +124,11 @@ # at least one WINS Server on the network. The default is NO. ; wins proxy = yes +# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names +# via DNS nslookups. The built-in default for versions 1.9.17 is yes, +# this has been changed in version 1.9.18 to no. + dns proxy = no + #============================ Share Definitions ============================== [homes] comment = Home Directories @@ -131,6 +141,7 @@ ; path = /usr/local/samba/lib/netlogon ; guest ok = yes ; writable = no +; share modes = no # Un-comment the following to provide a specific roving profile share -- cgit From 8964b0ad56804b119d39ed3a72a6cf0fb578a22e Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 14:43:00 +0000 Subject: NTDOMAIN.txt: describes how to set up samba as an NT PDC. it includes debugging assisting info. it is expected that this document turn into a user's document, rather than a debugger's document. cifsntdomain.txt : this is the "NT Domain Authentication (draft)" white paper, current version. if anyone think it's a bad idea to put a copy of this in here, i'm quite happy to remove it. --- docs/textdocs/NTDOMAIN.txt | 127 +++++ docs/textdocs/cifsntdomain.txt | 1059 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1186 insertions(+) create mode 100644 docs/textdocs/NTDOMAIN.txt create mode 100644 docs/textdocs/cifsntdomain.txt diff --git a/docs/textdocs/NTDOMAIN.txt b/docs/textdocs/NTDOMAIN.txt new file mode 100644 index 00000000000..f0a43b6ba5f --- /dev/null +++ b/docs/textdocs/NTDOMAIN.txt @@ -0,0 +1,127 @@ +Contributor: Luke Kenneth Casson Leighton +Created: October 20, 1997 +Updated: October 20, 1997 + +Subject: NT Domain Logons +=========================================================================== + +As of 1.9.18alpha1, Samba supports logins for NT 4.0 Workstations, without +the need, use or intervention of NT 4.0 Server. This document describes +how to set this up. Over the continued development of the 1.9.18alpha +series, this process (and therefore this document) should become simpler. + +The support is still experimental, so should be used at your own risk. + +NT is not as robust as you might have been led to believe: during the +development of the Domain Logon Support, one person reported having to +reinstall NT from scratch: their workstation had become totally unuseable. + +This *has* been reported to the NTBUGTRAQ@LISTSERV.NTBUGTRAQ.COM digest. + + +Domain Logons using 1.9.18alpha1 +================================ + +1) compile samba with -DNTDOMAIN + +2) carry out the following unix commands: + + touch /tmp/netlogon + touch /tmp/srvsvc + chmod 666 /tmp/netlogon + chmod 666 /tmp/srvsvc + +3) set up samba with encrypted passwords: see ENCRYPTION.txt (probably out + of date: you no longer need the DES libraries, but other than that, + ENCRYPTION.txt is current). + +4) for each workstation, add a line to smbpasswd with a username of MACHINE$ + and a password of "machine". this process will be automated in further + releases. + +5) if using NT server to log in, run the User Manager for Domains, and + add the capability to "Log in Locally" to the policies. + +6) set up the following parameters in smb.conf + +; substitute your workgroup here + workgroup = SAMBA + +; a description of domain sids can be found elsewhere. + domain sid = S-1-5-21-123-456-789-123 + +; tells workstations to use SAMBA as its Primary Domain Controller. + domain logons = yes + +7) make sure samba is running before the next step is carried out. if + this is your first time, just for fun you might like to switch the + debug log level to about 10. the NT pipes produces some very pretty + output when decoding requests and generating responses, which would + be particularly useful to see in tcpdump at some point. + +8) In the NT Network Settings, change the domain to SAMBA. Do + not attempt to create an account using the other part of the dialog: + it will fail at present. + + You should get a wonderful message saying "Welcome to the SAMBA Domain." + + If you don't, then please first increase your debug log levels and also + get a tcpdump (or preferably NetMonitor) trace and examine it carefully. + You should see a NETLOGON, a SAMLOGON on UDP port 138. If you don't, + then you probably don't have "domain logons = yes" or there is some other + problem in resolving the NetBIOS name SAMBA<1c>. + + On port 139, you should see a LSA_OPEN_POLICY, two LSA_QUERY_INFOs (one + for a domain SID of S-1-3... and another for S-1-5) and then an LSA_CLOSE + or two. If when you get a connection to the SMB pipe NETLOGON, if /netlogon + access is refused, then you probably haven't granted the correct access + permissions on the /tmp/netlogon file. Likewise for the srvsvc file. + + You may see a pipe connection to a wksta service being refused: this + is acceptable, we have found. You may also see a "Net Server Get Info" + being issued on the srvsvc pipe. + + Assuming you got the Welcome message, go through the obligatory reboot... + +9) When pressing Ctrl-Alt-Delete, the NT login box should have three entries. + If there is a delay of about twenty seconds between pressing Ctrl-Alt-Delete + and the appearance of this login dialog, then there might be a problem: + at this stage the workstation is issuing an LSA_ENUMTRUSTEDDOMAIN request + + The domain box should have two entries: the hostname and the SAMBA domain. + Any local accounts are under the hostname domain, from which you will be + able to shut down the machine etc. At present, we do not specify that + the NT user logging in is a member of any groups, so will have no + priveleges, including the ability to shut down the machine. + + Select the SAMBA domain, and type in a valid username and password for + which there is a valid entry in the samba server's smbpasswd LM/NT OWF + database. + + You should see an LSA_REQ_CHAL, followed by LSA_AUTH2, LSA_NET_SRV_PWSET, + and LSA_SAM_LOGON. The SAM Logon will be particularly large (the response + can be approximately 600 bytes) as it contains user info. + + Also, there will probably be a "Net Server Get Info" and a "Net Share Enum" + amongst this lot. If the SAM Logon is successful, the dialog should + disappear, and a standard SMB connection established to download the + profile specified in the SAM Logon (if it was). + + At this point, you _may_ encounter difficulties in creating a remote + profile, and the login may terminate (generating an LSA_SAM_LOGOFF). If + this occurs, then either find an existing profile on the samba server and + copy it into the location specified by the "logon path" smb.conf parameter + for the user logging in, or log in on the local machine, and use the + System | Profiles control panel to make a copy of the _local_ profile onto + the samba server. + +10) Play around. Look at the Samba Server: see if it can be found in the + browse lists. Check that it is accessible; run some applications. + Generally stress things. Laugh a lot. Logout of the NT machine + (generating an LSA_SAM_LOGOFF) and log back in again. Try logging in + two users simultaneously. Try logging the same user in twice. + Make Samba fall over, and then send bug reports to us, with NTDOM: at + the start of the subject line, as "samba-bugs@samba.anu.edu.au". + +Your reports, testing, patches and criticism will help us get this right. + diff --git a/docs/textdocs/cifsntdomain.txt b/docs/textdocs/cifsntdomain.txt new file mode 100644 index 00000000000..1a3b1c429f4 --- /dev/null +++ b/docs/textdocs/cifsntdomain.txt @@ -0,0 +1,1059 @@ +NT Domain Authentication +------------------------ + +Authors: - Luke Kenneth Casson Leighton (lkcl@switchboard.net) + - Paul Ashton (paul@argo.demon.co.uk) + +Version: 0.017 (20oct97) + +Distribution: Unlimited and encouraged, for the purposes of implementation + and comments. Feedback welcomed by the authors. + +Liability: Absolutely none accepted implicitly or explicitly, direct + or consequentially, for use, abuse, misuse, lack of use, + misunderstandings, mistakes, omissions, mis-information for + anything in or not in, related to or pertaining to this + document or anything else that a lawyer can think of or not + think of. + +Warning: Please bear in mind that an incorrect implementation of this + protocol can cause NT workstation to fail irrevocably, for + which the authors accept no liability (see above). Please + contact your vendor if you have any problems. + +Sources: - Packet Traces from Netmonitor (Service Pack 1 and above) + - Paul Ashton and Luke Leighton's other "NT Domain" doc. + - CIFS documentation - cifs6.txt + - CIFS documentation - cifsrap2.txt + +Original: http://mailhost.cb1.com/~lkcl/cifsntdomain.txt. + (Controlled copy maintained by lkcl@switchboard.net) + +Credits: - Paul Ashton: loads of work with Net Monitor; + understanding the NT authentication system; + reference implementation of the NT domain support on which + this document is originally based. + - Linus Nordberg: producing c-code from Paul's crypto spec. + - Windows Sourcer development team + +Contents: + +1) Introduction + +2) Structures and notes + + 2.1) Notes + 2.2) Structures + +3) Transact Named Pipe Header/Tail + + 3.1) Header + 3.2) Tail + +4) NTLSA Transact Named Pipe + + 4.1) LSA Open Policy + 4.2) LSA Query Info Policy + 4.3) LSA Enumerate Trusted Domains + 4.4) LSA Open Secret + 4.5) LSA Close + 4.6) LSA Lookup SIDS + 4.7) LSA Lookup Names + +5) NETLOGON rpc Transact Named Pipe + + 5.1) LSA Request Challenge + 5.2) LSA Authenticate 2 + 5.3) LSA Server Password Set + 5.4) LSA SAM Logon + 5.5) LSA SAM Logoff + +6) \\MAILSLOT\NET\NTLOGON + + 6.1) Query for PDC + 6.2) SAM Logon + +7) SRVSVC Transact Named Pipe + + 7.1) Net Share Enum + 7.2) Net Server Get Info + +Appendix: + +A1) Cryptographic side of NT Domain Authentication + + + +1) Introduction +--------------- + + +This document contains information to provide an NT workstation with login +services, without the need for an NT server. + +It should be possible to select a domain instead of a workgroup (in the NT +workstation's TCP/IP settings) and after the obligatory reboot, type in a +username, password, select a domain and successfully log in. I would +appreciate any feedback on your experiences with this process, and any +comments, corrections and additions to this document. + + +The packets described here can be easily derived from (and are probably +better understood using) Netmon.exe. You will need to use the version +of Netmon that matches your system, in order to correctly decode the +NETLOGON, lsarpc and srvsvc Transact pipes. This document is derived from +NT Service Pack 1 and its corresponding version of Netmon. It is intended +that an annotated packet trace be produced, which will likely be more +instructive than this document. + +Also needed, to fully implement NT Domain Login Services, is the +document describing the cryptographic part of the NT authentication. +This document is available from comp.protocols.smb; from the ntsecurity.net +digest and from the samba digest, amongst other sources. + +A copy is available from: + +http://ntbugtraq.rc.on.ca/SCRIPTS/WA.EXE?A2=ind9708&L=ntbugtraq&O=A&P=2935 +http://mailhost.cb1.com/~lkcl/crypt.html + + +A c-code implementation, provided by Linus Nordberg <linus@incolumitas.se> +of this protocol is available from: + +http://samba.anu.edu.au/cgi-bin/mfs/01/digest/1997/97aug/0391.html +http://mailhost.cb1.com/~lkcl/crypt.txt + + +Also used to provide debugging information is the Check Build version of +NT workstation, and enabling full debugging in NETLOGON. This is +achieved by setting the following REG_SZ registry key to 0x1ffffff: + +HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters + +- Incorrect direct editing of the registry can cause your machine to fail. + Then again, so can incorrect implementation of this protocol. + See "Liability:" above. + + +Bear in mind that each packet over-the-wire will have its origin in an +API call. Therefore, there are likely to be structures, enumerations +and defines that are usefully documented elsewhere. + + +This document is by no means complete or authoritative. Missing sections +include, but are not limited to: + +- the meaning (and use by NT) of SIDs and RIDs. + +- mappings of RIDs to usernames (and vice-versa). + +- what a User ID is and what a Group ID is. + +- the exact meaning/definition of various magic constants or enumerations. + +- the reply error code and use of that error code when a workstation + becomes a member of a domain (to be described later). Failure to + return this error code will make the workstation report that it is + already a member of the domain. + +- the cryptographic side of the NetrServerPasswordSet command, which would + allow the workstation to change its password. This password is used to + generate the long-term session key. [It is possible to reject this + command, and keep the default workstation password]. + + +2) Notes and Structures +----------------------- + + +2.1) Notes +---------- + +- In the SMB Transact pipes, some "Structures", described here, appear to be + 4-byte aligned with the SMB header, at their start. Exactly which + "Structures" need aligning is not precisely known or documented. + +- In the UDP NTLOGON Mailslots, some "Structures", described here, appear to be + 2-byte aligned with the start of the mailslot, at their start. + +- Domain SID is of the format S-revision-version-auth1-auth2...authN. + e.g S-1-5-123-456-789-123-456. the 5 could be a sub-revision. + +- any undocumented buffer pointers must be non-zero if the string buffer it + refers to contains characters. exactly what value they should be is unknown. + 0x0000 0002 seems to do the trick to indicate that the buffer exists. a + NULL buffer pointer indicates that the string buffer is of zero length. + If the buffer pointer is NULL, then it is suspected that the structure it + refers to is NOT put into (or taken out of) the SMB data stream. This is + empirically derived from, for example, the LSA SAM Logon response packet, + where if the buffer pointer is NULL, the user information is not inserted + into the data stream. Exactly what happens with an array of buffer pointers + is not known, although an educated guess can be made. + +- an array of structures (a container) appears to have a count and a pointer. + if the count is zero, the pointer is also zero. no further data is put + into or taken out of the SMB data stream. if the count is non-zero, then + the pointer is also non-zero. immediately following the pointer is the + count again, followed by an array of container sub-structures. the count + appears a third time after the last sub-structure. + + + +2.2) Structures +--------------- + +- sizeof VOID* is 32 bits. + +- sizeof char is 8 bits. + +- UTIME is 32 bits, indicating time in seconds since 01jan1970. documented + in cifs6.txt (section 3.5 page, page 30). + +- NTTIME is 64 bits. documented in cifs6.txt (section 3.5 page, page 30). + +- DOM_SID (domain SID structure) : + + UINT32 num of sub-authorities in domain SID + UINT8 SID revision number + UINT8 num of sub-authorities in domain SID + UINT8[6] 6 bytes for domain SID - Identifier Authority. + UINT16[n_subauths] domain SID sub-authorities + + Note: the domain SID is documented elsewhere. + +- STR (string) : + + char[] null-terminated string of ascii characters. + +- UNIHDR (unicode string header) : + + UINT16 length of unicode string + UINT16 max length of unicode string + UINT32 4 - undocumented. + +- UNIHDR2 (unicode string header plus buffer pointer) : + + UNIHDR unicode string header + VOID* undocumented buffer pointer + +- UNISTR (unicode string) : + + UINT16[] null-terminated string of unicode characters. + +- NAME (length-indicated unicode string) : + + UINT32 length of unicode string + UINT16[] null-terminated string of unicode characters. + +- UNISTR2 (aligned unicode string) : + + UINT8[] padding to get unicode string 4-byte aligned + with the start of the SMB header. + UINT32 max length of unicode string + UINT32 0 - undocumented + UINT32 length of unicode string + UINT16[] string of uncode characters. + +- POL_HND (LSA policy handle) : + + char[20] policy handle + +- DOM_SID2 (domain SID structure, SIDS stored in unicode) : + + UINT32 5 - SID type + UINT32 0 - undocumented + UNIHDR2 domain SID unicode string header + UNISTR domain SID unicode string + + Note: there is a conflict between the unicode string header and the + unicode string itself as to which to use to indicate string + length. this will need to be resolved. + + Note: the SID type indicates, for example, an alias; a well-known group etc. + this is documented somewhere. + +- DOM_RID (domain RID structure) : + + UINT32 5 - well-known SID. 1 - user SID (see ShowACLs) + UINT32 5 - undocumented + UINT32 domain RID + UINT32 0 - domain index out of above reference domains + + +- LOG_INFO (server, account, client structure) : + + Note: logon server name starts with two '\' characters and is upper case. + + Note: account name is the logon client name from the LSA Request Challenge, + with a $ on the end of it, in upper case. + + VOID* undocumented buffer pointer + UNISTR2 logon server unicode string + UNISTR2 account name unicode string + UINT16 sec_chan - security channel type + UNISTR2 logon client machine unicode string + +- CLNT_SRV (server, client names structure) : + + Note: logon server name starts with two '\' characters and is upper case. + + VOID* undocumented buffer pointer + UNISTR2 logon server unicode string + VOID* undocumented buffer pointer + UNISTR2 logon client machine unicode string + +- CREDS (credentials + time stamp) + + char[8] credentials + UTIME time stamp + +- CLNT_INFO2 (server, client structure, client credentials) : + + Note: whenever this structure appears in a request, you must take a copy + of the client-calculated credentials received, because they will be + used in subsequent credential checks. the presumed intention is to + maintain an authenticated request/response trail. + + CLNT_SRV client and server names + UINT8[] ???? padding, for 4-byte alignment with SMB header. + VOID* pointer to client credentials. + CREDS client-calculated credentials + client time + +- CLNT_INFO (server, account, client structure, client credentials) : + + Note: whenever this structure appears in a request, you must take a copy + of the client-calculated credentials received, because they will be + used in subsequent credential checks. the presumed intention is to + maintain an authenticated request/response trail. + + LOG_INFO logon account info + CREDS client-calculated credentials + client time + +- ID_INFO_1 (id info structure, auth level 1) : + + VOID* ptr_id_info_1 + UNIHDR domain name unicode header + UINT32 param control + UINT64 logon ID + UNIHDR user name unicode header + UNIHDR workgroup name unicode header + char[16] rc4 LM OWF Password + char[16] rc4 NT OWF Password + UNISTR2 domain name unicode string + UNISTR2 user name unicode string + UNISTR2 workgroup name unicode string + +- SAM_INFO (sam logon/logoff id info structure) : + + CLNT_INFO2 client identification/authentication info + VOID* pointer to return credentials. + CRED return credentials - ignored. + UINT16 logon level + UINT16 switch value + + switch (switch_value) + case 1: + { + ID_INFO_1 id_info_1; + } + +- GID (group id info) : + + UINT32 group id + UINT32 user attributes (only used by NT 3.1 and 3.51) + +- DOM_REF (domain reference info) : + + VOID* undocumented buffer pointer. + UINT32 num referenced domains? + VOID* undocumented domain name buffer pointer. + UINT32 32 - max number of entries + UINT32 4 - num referenced domains? + + UNIHDR2 domain name unicode string header + UNIHDR2[num_ref_doms-1] referenced domain unicode string headers + + UNISTR domain name unicode string + DOM_SID[num_ref_doms] referenced domain SIDs + +- DOM_INFO (domain info, levels 3 and 5 are the same)) : + + UINT8[] ??? padding to get 4-byte alignment with start of SMB header + UINT16 domain name string length * 2 + UINT16 domain name string length * 2 + VOID* undocumented domain name string buffer pointer + VOID* undocumented domain SID string buffer pointer + UNISTR2 domain name (unicode string) + DOM_SID domain SID + +- USER_INFO (user logon info) : + + NTTIME logon time + NTTIME logoff time + NTTIME kickoff time + NTTIME password last set time + NTTIME password can change time + NTTIME password must change time + + UNIHDR username unicode string header + UNIHDR user's full name unicode string header + UNIHDR logon script unicode string header + UNIHDR profile path unicode string header + UNIHDR home directory unicode string header + UNIHDR home directory drive unicode string header + + UINT16 logon count + UINT16 bad password count + + UINT32 User ID + UINT32 Group ID + UINT32 num groups + VOID* undocumented buffer pointer to groups. + + UINT32 user flags + char[16] unused user session key + + UNIHDR logon server unicode string header + UNIHDR logon domain unicode string header + VOID* undocumented logon domain id pointer + char[40] 40 undocumented padding bytes. future expansion? + + UINT32 0 - num_other_sids? + VOID* NULL - undocumented pointer to other domain SIDs. + + UNISTR2 username unicode string + UNISTR2 user's full name unicode string + UNISTR2 logon script unicode string + UNISTR2 profile path unicode string + UNISTR2 home directory unicode string + UNISTR2 home directory drive unicode string + + UINT32 num groups + GID[num_groups] group info + + UNISTR2 logon server unicode string + UNISTR2 logon domain unicode string + + DOM_SID domain SID + DOM_SID[num_sids] other domain SIDs? + +- SH_INFO_1_PTR (pointers to level 1 share info strings): + +Note: see cifsrap2.txt section5, page 10. + + 0 for shi1_type indicates a Disk. + 1 for shi1_type indicates a Print Queue. + 2 for shi1_type indicates a Device. + 3 for shi1_type indicates an IPC pipe. + 0x8000 0000 (top bit set in shi1_type) indicates a hidden share. + + VOID* shi1_netname - pointer to net name + UINT32 shi1_type - type of share. 0 - undocumented. + VOID* shi1_remark - pointer to comment. + +- SH_INFO_1_STR (level 1 share info strings) : + + UNISTR2 shi1_netname - unicode string of net name + UNISTR2 shi1_remark - unicode string of comment. + +- SHARE_INFO_1_CTR : + + share container with 0 entries: + + UINT32 0 - EntriesRead + UINT32 0 - Buffer + + share container with > 0 entries: + + UINT32 EntriesRead + UINT32 non-zero - Buffer + UINT32 EntriesRead + + SH_INFO_1_PTR[EntriesRead] share entry pointers + SH_INFO_1_STR[EntriesRead] share entry strings + + UINT8[] padding to get unicode string 4-byte + aligned with start of the SMB header. + UINT32 EntriesRead + UINT32 0 - padding + +- SERVER_INFO_101 : + +Note: see cifs6.txt section 6.4 - the fields described therein will be + of assistance here. for example, the type listed below is the + same as fServerType, which is described in 6.4.1. + + SV_TYPE_WORKSTATION 0x00000001 All workstations + SV_TYPE_SERVER 0x00000002 All servers + SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL + server + SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller + SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller + SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource + service + SV_TYPE_AFP 0x00000040 Apple File Protocol servers + SV_TYPE_NOVELL 0x00000080 Novell servers + SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member + SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue + SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. + SV_TYPE_XENIX_SERVER 0x00000800 Xenix server + SV_TYPE_NT 0x00001000 NT server + SV_TYPE_WFW 0x00002000 Server running Windows for + + SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server + SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser + service + SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server + SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server + SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server + SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked + "local" + SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszServer + and pszDomain parameters must be + NULL. + + UINT32 500 - platform_id + VOID* pointer to name + UINT32 5 - major version + UINT32 4 - minor version + UINT32 type (SV_TYPE_... bit field) + VOID* pointer to comment + + UNISTR2 sv101_name - unicode string of server name + UNISTR2 sv_101_comment - unicode string of server comment. + + UINT8[] padding to get unicode string 4-byte + aligned with start of the SMB header. + + + +3) Transact Named Pipe Header/Tail +---------------------------------- + +Interesting note: if you set packed data representation to 0x0100 0000 then +all 4-byte and 2-byte word ordering is turned around. + +3.1) Header +----------- + +The start of each of the NTLSA and NETLOGON named pipes begins with: + +00 UINT8 5 - RPC major version +01 UINT8 0 - RPC minor version +02 UINT8 2 - RPC response packet +03 UINT8 3 - first frag + last frag +04 UINT32 0x1000 0000 - packed data representation +08 UINT16 fragment length - data size (bytes) inc header and tail. +0A UINT16 0 - authentication length +0C UINT32 call identifier. matches 12th UINT32 of incoming RPC data. +10 UINT32 allocation hint - data size (bytes) minus header and tail. +14 UINT16 0 - presentation context identifier +16 UINT8 0 - cancel count +17 UINT8 0 - reserved +18 ...... start of data (goes on for allocation_hint bytes) + + +3.2 Tail +-------- + +The end of each of the NTLSA and NETLOGON named pipes ends with: + + ...... end of data + UINT32 return code + + + +4) NTLSA Transact Named Pipe +---------------------------- + +Defines for this pipe, identifying the query are: + +- LSA Open Policy: 0x2c +- LSA Query Info Policy: 0x07 +- LSA Enumerate Trusted Domains: 0x0d +- LSA Open Secret: 0xff +- LSA Lookup SIDs: 0xfe +- LSA Lookup Names: 0xfd +- LSA Close: 0x00 + + +4.1) LSA Open Policy +-------------------- + +Note: The policy handle can be anything you like. + +Request: + + no extra data. + +Response: + + POL_HND LSA policy handle + + return 0 - indicates success + + +4.2) LSA Query Info Policy +-------------------------- + +Note: The info class in response must be the same as that in the request. + +Request: + + POL_HND LSA policy handle + UINT16 info class (also a policy handle?) + +Response: + + VOID* undocumented buffer pointer + UINT16 info class (same as info class in request). + + switch (info class) + case 3: + case 5: + { + DOM_INFO domain info, levels 3 and 5 (are the same). + } + + return 0 - indicates success + + +4.3) LSA Enumerate Trusted Domains +---------------------------------- + +Request: + + no extra data + +Response: + + UINT32 0 - enumeration context + UINT32 0 - entries read + UINT32 0 - trust information + + return 0x8000 001a - "no trusted domains" success code + + +4.4) LSA Open Secret +-------------------- + +Request: + + no extra data + +Response: + + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + + return 0x0C00 0034 - "no such secret" success code + + +4.5) LSA Close +-------------- + +Request: + + no extra data + +Response: + + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + UINT32 0 - undocumented + + return 0 - indicates success + + +4.6) LSA Lookup SIDS +-------------------- + +Note: num_entries in response must be same as num_entries in request. + +Request: + + POL_HND LSA policy handle + UINT32 num_entries + VOID* undocumented domain SID buffer pointer + VOID* undocumented domain name buffer pointer + VOID*[num_entries] undocumented domain SID pointers to be looked up. + DOM_SID[num_entries] domain SIDs to be looked up. + char[16] completely undocumented 16 bytes. + +Response: + + DOM_REF domain reference response + + UINT32 num_entries (listed above) + VOID* undocumented buffer pointer + + UINT32 num_entries (listed above) + DOM_SID2[num_entries] domain SIDs (from Request, listed above). + + UINT32 num_entries (listed above) + + return 0 - indicates success + + +4.7) LSA Lookup Names +--------------------- + +Note: num_entries in response must be same as num_entries in request. + +Request: + + POL_HND LSA policy handle + UINT32 num_entries + UINT32 num_entries + VOID* undocumented domain SID buffer pointer + VOID* undocumented domain name buffer pointer + NAME[num_entries] names to be looked up. + char[] undocumented bytes - falsely translated SID structure? + +Response: + + DOM_REF domain reference response + + UINT32 num_entries (listed above) + VOID* undocumented buffer pointer + + UINT32 num_entries (listed above) + DOM_RID[num_entries] domain SIDs (from Request, listed above). + + UINT32 num_entries (listed above) + + return 0 - indicates success + + + +5) NETLOGON rpc Transact Named Pipe +----------------------------------- + +Defines for this pipe, identifying the query are: + +- LSA Request Challenge: 0x04 +- LSA Server Password Set: 0x06 +- LSA SAM Logon: 0x02 +- LSA SAM Logoff: 0xfc +- LSA Auth 2: 0x0f +- LSA Logon Control: 0x0e + + +5.1) LSA Request Challenge +-------------------------- + +Note: logon server name starts with two '\' characters and is upper case. + +Note: logon client is the machine, not the user. + +Note: the initial LanManager password hash, against which the challenge + is issued, is the machine name itself (lower case). there will be + calls issued (LSA Server Password Set) which will change this, later. + refusing these calls allows you to always deal with the same password + (i.e the LM# of the machine name in lower case). + +Request: + + VOID* undocumented buffer pointer + UNISTR2 logon server unicode string + UNISTR2 logon client unicode string + char[8] client challenge + +Response: + + char[8] server challenge + + return 0 - indicates success + + + +5.2) LSA Authenticate 2 +----------------------- + +Note: in between request and response, calculate the client credentials, + and check them against the client-calculated credentials (this + process uses the previously received client credentials). + +Note: neg_flags in the response is the same as that in the request. + +Note: you must take a copy of the client-calculated credentials received + here, because they will be used in subsequent authentication packets. + +Request: + + LOG_INFO client identification info + + char[8] client-calculated credentials + UINT8[] padding to 4-byte align with start of SMB header. + UINT32 neg_flags - negotiated flags (usual value is 0x0000 01ff) + +Response: + + char[8] server credentials. + UINT32 neg_flags - same as neg_flags in request. + + return 0 - indicates success. failure value unknown. + + +5.3) LSA Server Password Set +---------------------------- + +Note: the new password is suspected to be a DES encryption using the old + password to generate the key. + +Note: in between request and response, calculate the client credentials, + and check them against the client-calculated credentials (this + process uses the previously received client credentials). + +Note: the server credentials are constructed from the client-calculated + credentials and the client time + 1 second. + +Note: you must take a copy of the client-calculated credentials received + here, because they will be used in subsequent authentication packets. + +Request: + + CLNT_INFO client identification/authentication info + char[] new password - undocumented. + +Response: + + CREDS server credentials. server time stamp appears to be ignored. + + return 0 - indicates success; 0xC000 006a indicates failure + + +5.4) LSA SAM Logon +------------------ + +Note: valid_user is True iff the username and password hash are valid for + the requested domain. + +Request: + + SAM_INFO sam_id structure + +Response: + + VOID* undocumented buffer pointer + CREDS server credentials. server time stamp appears to be ignored. + + if (valid_user) + { + UINT16 3 - switch value indicating USER_INFO structure. + VOID* non-zero - pointer to USER_INFO structure + USER_INFO user logon information + + UINT32 1 - Authoritative response; 0 - Non-Auth? + + return 0 - indicates success + } + else + { + UINT16 0 - switch value. value to indicate no user presumed. + VOID* 0x0000 0000 - indicates no USER_INFO structure. + + UINT32 1 - Authoritative response; 0 - Non-Auth? + + return 0xC000 0064 - NT_STATUS_NO_SUCH_USER. + } + + +5.5) LSA SAM Logoff +-------------------- + +Note: presumably, the SAM_INFO structure is validated, and a (currently + undocumented) error code returned if the Logoff is invalid. + +Request: + + SAM_INFO sam_id structure + +Response: + + VOID* undocumented buffer pointer + CREDS server credentials. server time stamp appears to be ignored. + + return 0 - indicates success. undocumented failure indication. + + +6) \\MAILSLOT\NET\NTLOGON +------------------------- + +Note: mailslots will contain a response mailslot, to which the response + should be sent. the target NetBIOS name is REQUEST_NAME<20>, where + REQUEST_NAME is the name of the machine that sent the request. + + +6.1) Query for PDC +------------------ + +Note: NTversion, LMNTtoken, LM20token in response are the same as those + given in the request. + +Request: + + UINT16 0x0007 - Query for PDC + STR machine name + STR response mailslot + UINT8[] padding to 2-byte align with start of mailslot. + UNISTR machine name + UINT32 NTversion + UINT16 LMNTtoken + UINT16 LM20token + +Response: + + UINT16 0x000A - Respose to Query for PDC + STR machine name (in uppercase) + UINT8[] padding to 2-byte align with start of mailslot. + UNISTR machine name + UNISTR domain name + UINT32 NTversion (same as received in request) + UINT16 LMNTtoken (same as received in request) + UINT16 LM20token (same as received in request) + + +6.2) SAM Logon +-------------- + +Note: machine name in response is preceded by two '\' characters. + +Note: NTversion, LMNTtoken, LM20token in response are the same as those + given in the request. + +Note: user name in the response is presumably the same as that in the request. + +Request: + + UINT16 0x0012 - SAM Logon + UINT16 request count + UNISTR machine name + UNISTR user name + STR response mailslot + UINT32 alloweable account + UINT32 domain SID size + char[sid_size] domain SID, of sid_size bytes. + UINT8[] ???? padding to 4? 2? -byte align with start of mailslot. + UINT32 NTversion + UINT16 LMNTtoken + UINT16 LM20token + +Response: + + UINT16 0x0013 - Response to SAM Logon + UNISTR machine name + UNISTR user name - workstation trust account + UNISTR domain name + UINT32 NTversion + UINT16 LMNTtoken + UINT16 LM20token + + + +7) SRVSVC Transact Named Pipe +----------------------------- + + +Defines for this pipe, identifying the query are: + +- Net Share Enum : 0x0f +- Net Server Get Info : 0x15 + + +7.1) Net Share Enum +------------------ + +Note: share level and switch value in the response are presumably the + same as those in the request. + +Note: cifsrap2.txt (section 5) may be of limited assistance here. + +Request: + + VOID* pointer (to server name?) + UNISTR2 server name + + UINT8[] padding to get unicode string 4-byte aligned + with the start of the SMB header. + + UINT32 share level + UINT32 switch value + + VOID* pointer to SHARE_INFO_1_CTR + SHARE_INFO_1_CTR share info with 0 entries + + UINT32 preferred maximum length (0xffff ffff) + +Response: + + UINT32 share level + UINT32 switch value + + VOID* pointer to SHARE_INFO_1_CTR + SHARE_INFO_1_CTR share info (only added if share info ptr is non-zero) + + return 0 - indicates success + + +7.2) Net Server Get Info +------------------ + +Note: level is the same value as in the request. + +Request: + + UNISTR2 server name + UINT32 switch level + +Response: + + UINT32 switch level + VOID* pointer to SERVER_INFO_101 + + SERVER_INFO_101 server info (only added if server info ptr is non-zero) + + return 0 - indicates success + + + +Appendix +-------- + +A1) Cryptographic side of NT Domain Authentication +-------------------------------------------------- + +Definitions +----------- + +Add(A1,A2): Intel byte ordered addition of corresponding 4 byte + words in arrays A1 and A2 + +E(K,D): DES ECB encryption of 8 byte data D using 7 byte key K + +lmowf(): Lan man hash + +ntowf(): NT hash + +PW: md4(machine_password) =3D=3D md4(lsadump $machine.acc) + =3D=3D pwdump(machine$) + (initially) =3D=3D md4(lmowf(unicode(machine))) + +RC4(K,Lk,D,Ld): RC4 encryption of data D of length Ld with key K + of length Lk + +v[m..n(,l)]: subset of v from bytes m to n, optionally padded + with zeroes to length l + +Cred(K,D): E(K[7..7,7],E(K[0..6],D)) computes a credential + +Time(): 4 byte current time + +Cc,Cs: 8 byte client and server challenges +Rc,Rs: 8 byte client and server credentials + -- cgit From 38287a59ae1d4053d4cd2f53a141a5c826c21efd Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 14:46:05 +0000 Subject: added copyright to headers. --- docs/textdocs/NTDOMAIN.txt | 3 ++- docs/textdocs/cifsntdomain.txt | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/textdocs/NTDOMAIN.txt b/docs/textdocs/NTDOMAIN.txt index f0a43b6ba5f..6b486b7f2a6 100644 --- a/docs/textdocs/NTDOMAIN.txt +++ b/docs/textdocs/NTDOMAIN.txt @@ -1,4 +1,5 @@ -Contributor: Luke Kenneth Casson Leighton +Contributor: Luke Kenneth Casson Leighton (samba-bugs@samba.anu.edu.au) + Copyright (C) 1997 Luke Kenneth Casson Leighton Created: October 20, 1997 Updated: October 20, 1997 diff --git a/docs/textdocs/cifsntdomain.txt b/docs/textdocs/cifsntdomain.txt index 1a3b1c429f4..175bb33ea6d 100644 --- a/docs/textdocs/cifsntdomain.txt +++ b/docs/textdocs/cifsntdomain.txt @@ -2,7 +2,9 @@ NT Domain Authentication ------------------------ Authors: - Luke Kenneth Casson Leighton (lkcl@switchboard.net) + Copyright (C) 1997 Luke Kenneth Casson Leighton - Paul Ashton (paul@argo.demon.co.uk) + Copyright (C) 1997 Paul Ashton Version: 0.017 (20oct97) -- cgit From 6d67eddcdffd26b0fa7f97ed3fa08ec002566367 Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 16:24:14 +0000 Subject: added description of parameters: domain sid domain groups logon drive logon path --- docs/manpages/smb.conf.5 | 77 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 9b8dfd3f280..432ef7035c3 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -266,6 +266,10 @@ personality". %M = the internet name of the client machine +%N = the name of your NIS home directory server. This is obtained from +your NIS auto.map entry. If you have not compiled Samba with -DAUTOMOUNT +then this value will be the same as %L. + %d = The process id of the current server process %a = the architecture of the remote machine. Only some are recognised, @@ -349,6 +353,10 @@ dns proxy domain controller +domain sid + +domain group + domain logons domain master @@ -381,6 +389,10 @@ log file log level +logon drive + +logon home + logon path logon script @@ -1153,6 +1165,7 @@ files. .B Example: directory mask = 0775 + .SS directory mode (S) See .B directory mask. @@ -1183,6 +1196,37 @@ logons from Win95 machines to. You should never need to set this parameter. .B Default: domain controller = no +.SS domain groups (G) + +Specifies the NT Domain groups that the user belongs to, and the attributes +associated with that group. This parameter is a white-space separated list +of group ids (in decimal), followed by an option attribute (in decimal) which +defaults to a value of 7 if not specified. A group id and the user attributes +associated with it are separated by "/". + +.B +It is known that attributes are ignored by NT 4.0 Workstation, but not by +NT 3.51 Workstation. Furthermore, no information on the exact meaning of +NT Domain groups is presently known. + +.B Default: + domain groups = 776/7 + +.B Example: + domain groups = 776 1024/7 777 + +.SS domain sid (G) + +Specifies the SID when using Samba as a Logon Server for NT Workstations. +The format of SIDs supported by samba at present is S-1-N-nnn-nnn-nnn-nnn-nnn. +The number N indicates the number of sub-authorities (nnn). + +.B Default: + domain sid = none + +.B Example: + domain sid = S-1-5-21-123-456-789-123 + .SS domain logons (G) If set to true, the Samba server will serve Windows 95 domain logons @@ -1583,6 +1627,7 @@ The lock files are used to implement the "max connections" option. .B Example: lock directory = /usr/local/samba/var/locks + .SS locking (S) This controls whether or not locking will be performed by the server in response to lock requests from the client. @@ -1618,6 +1663,30 @@ separate log files for each user or machine. .SS log level (G) see "debug level" +.SS logon drive (G) + +This parameter specifies the local path to which the home directory +will be connected (see "logon home") and is only used by NT Workstations. + +.B Example: + logon drive = h: + +.SS logon home (G) + +This parameter specifies the home directory location when a Win95 or +NT Workstation logs into a Samba PDC. It allows you to do "NET USE +H: /HOME" from a command prompt, for example. + +.B +This option takes the standard substitutions, allowing you to have +separate logon scripts for each user or machine. + +.B Example: + logon home = "\\\\remote_smb_server\\%U" + +.B Default: + logon home = "\\\\%N\\%U" + .SS logon path (G) This parameter specifies the home directory where roaming profiles @@ -1642,10 +1711,14 @@ read-only - rename it to USER.MAN to achieve the desired effect Windows clients can sometimes maintain a connection to the [homes] share, even though there is no user logged in. Therefore, it is vital that the logon path does not include a reference to the -homes share (i.e \\\\%L\\HOMES\profile_path will cause problems). +homes share (i.e \\\\%N\\HOMES\profile_path will cause problems). + +.B +This option takes the standard substitutions, allowing you to have +separate logon scripts for each user or machine. .B Default: - logon path = \\\\%L\\%U\\profile + logon path = \\\\%N\\%U\\profile .B Example: logon path = \\\\PROFILESERVER\\HOME_DIR\\%U\\PROFILE -- cgit From c6e37d8db0cd89a84a54a0cedfeacf50fb3f7a4c Mon Sep 17 00:00:00 2001 From: Luke Leighton <lkcl@samba.org> Date: Mon, 20 Oct 1997 16:25:19 +0000 Subject: added "domain groups" parameter, allowing you to specify the groups that the user belongs to. it would be nice to know exactly what the domain groups _are_.... --- source/include/proto.h | 4 +++- source/lib/util.c | 28 ++++++++++++++++++++++++++++ source/param/loadparm.c | 4 ++++ source/pipenetlog.c | 8 ++++++-- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index e12ea4002d7..97212ff74da 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -165,6 +165,7 @@ char *lp_nis_home_map_name(void); char *lp_announce_version(void); char *lp_netbios_aliases(void); char *lp_domainsid(void); +char *lp_domain_groups(void); BOOL lp_dns_proxy(void); BOOL lp_wins_support(void); BOOL lp_wins_proxy(void); @@ -1090,7 +1091,7 @@ BOOL zero_ip(struct in_addr ip); void reset_globals_after_fork(); char *client_name(void); char *client_addr(void); -char *automount_server(char *username); +char *automount_server(char *user_name); void standard_sub_basic(char *str); BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); int PutUniCode(char *dst,char *src); @@ -1122,3 +1123,4 @@ char *align2(char *q, char *base); char *align_offset(char *q, char *base, int align_offset_len); void dump_data(int level,char *buf1,int len); char *tab_depth(int depth); +int make_domain_gids(char *gids_str, DOM_GID *gids); diff --git a/source/lib/util.c b/source/lib/util.c index 9295d9ae73f..ec0f9f0efc9 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -4508,3 +4508,31 @@ char *tab_depth(int depth) spaces[depth * 4] = 0; return spaces; } + +int make_domain_gids(char *gids_str, DOM_GID *gids) +{ + char *ptr; + pstring s2; + int count; + + DEBUG(4,("make_domain_gids: %s\n", gids_str)); + + if (gids_str == NULL || *gids_str == 0) return 0; + + for (count = 0, ptr = gids_str; next_token(&ptr, s2, NULL) && count < LSA_MAX_GROUPS; count++) + { + /* the entries are of the form GID/ATTR, ATTR being optional.*/ + char *attr; + + attr = strchr(s2,'/'); + if (attr) *attr++ = 0; + if (!attr || !*attr) attr = "7"; /* default value for attribute is 7 */ + + gids[count].gid = atoi(s2); + gids[count].attr = atoi(attr); + + DEBUG(5,("group id: %d attr: %d\n", gids[count].gid, gids[count].attr)); + } + + return count; +} diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 9a268193978..32fc538886a 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -143,6 +143,7 @@ typedef struct char *szAnnounceVersion; /* This is initialised in init_globals */ char *szNetbiosAliases; char *szDomainSID; + char *szDomainGroups; int max_log_size; int mangled_stack; int max_xmit; @@ -442,6 +443,7 @@ struct parm_struct {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars}, {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL}, {"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL}, + {"domain groups", P_USTRING, P_GLOBAL, &Globals.szDomainGroups, NULL}, {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL}, {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL}, {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set}, @@ -629,6 +631,7 @@ static void init_globals(void) /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */ string_set(&Globals.szLogonHome, "\\\\%N\\%U"); string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile"); + string_set(&Globals.szDomainGroups, "776/7"); Globals.bLoadPrinters = True; Globals.bUseRhosts = False; Globals.max_packet = 65535; @@ -858,6 +861,7 @@ FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion) FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases) FN_GLOBAL_STRING(lp_domainsid,&Globals.szDomainSID) +FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups) FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) diff --git a/source/pipenetlog.c b/source/pipenetlog.c index d407e006610..0563a615913 100644 --- a/source/pipenetlog.c +++ b/source/pipenetlog.c @@ -499,6 +499,8 @@ static void api_lsa_sam_logon( user_struct *vuser, if (vuser != NULL) { + DOM_GID gids[LSA_MAX_GROUPS]; + int num_gids; NTTIME dummy_time; pstring logon_script; pstring profile_path; @@ -527,6 +529,8 @@ static void api_lsa_sam_logon( user_struct *vuser, pstrcpy(home_drive , lp_logon_drive ()); pstrcpy(home_dir , lp_logon_home ()); + num_gids = make_domain_gids(lp_domain_groups(), gids); + sam_logon_in_ssb = False; pstrcpy(my_name , myname ); @@ -553,8 +557,8 @@ static void api_lsa_sam_logon( user_struct *vuser, vuser->uid, /* uint32 user_id */ vuser->gid, /* uint32 group_id */ - 0, /* uint32 num_groups */ - NULL, /* DOM_GID *gids */ + num_gids, /* uint32 num_groups */ + gids, /* DOM_GID *gids */ 0x20, /* uint32 user_flgs */ NULL, /* char sess_key[16] */ -- cgit From 41a1d81c112a82ad2ae1b3c4ee81051f133ce1ed Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Mon, 20 Oct 1997 18:52:04 +0000 Subject: loadparm.c: Changed 'interfaces only' parameter to 'bind interfaces only'. Added 'dos filetimes' parameter for UTIME fix. locking_shm.c: Fixed typo (sorry Andrew :-). namepacket.c: Changed lp_interfaces_only() to lp_bind_interfaces_only(). proto.h: The usual. reply.c: Made filetime calls use new file_utime call (wrapper for sys_utime). server.c: Made filetime calls use new file_utime call (wrapper for sys_utime). system.c: Added Andrew's sanity checks to times in sys_utime(). time.c: Moved set_filetime() to server.c. Made null_mtime() global. trans2.c: Made filetime calls use new file_utime call (wrapper for sys_utime). Jeremy (jallison@whistle.com) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/include/proto.h | 7 +++-- source/lib/system.c | 9 ++++++ source/lib/time.c | 21 +------------ source/locking/locking_shm.c | 2 +- source/namepacket.c | 4 +-- source/param/loadparm.c | 12 +++++--- source/smbd/reply.c | 8 ++--- source/smbd/server.c | 72 +++++++++++++++++++++++++++++++++++++++----- source/smbd/trans2.c | 2 +- 9 files changed, 95 insertions(+), 42 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index 97212ff74da..8e819543130 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -188,7 +188,7 @@ BOOL lp_browse_list(void); BOOL lp_unix_realname(void); BOOL lp_nis_home_map(void); BOOL lp_time_server(void); -BOOL lp_interfaces_only(void); +BOOL lp_bind_interfaces_only(void); int lp_os_level(void); int lp_max_ttl(void); int lp_max_log_size(void); @@ -273,6 +273,7 @@ BOOL lp_map_system(int ); BOOL lp_delete_readonly(int ); BOOL lp_fake_oplocks(int ); BOOL lp_recursive_veto_delete(int ); +BOOL lp_dos_filetimes(int ); int lp_create_mode(int ); int lp_force_create_mode(int ); int lp_dir_mode(int ); @@ -777,6 +778,8 @@ void killkids(void); mode_t unix_mode(int cnum,int dosmode); int dos_mode(int cnum,char *path,struct stat *sbuf); int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st); +int file_utime(int cnum, char *fname, struct utimbuf *times); +BOOL set_filetime(int cnum, char *fname, time_t mtime); BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path); int disk_free(char *path,int *bsize,int *dfree,int *dsize); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); @@ -944,13 +947,13 @@ int TimeDiff(time_t t); struct tm *LocalTime(time_t *t); time_t interpret_long_date(char *p); void put_long_date(char *p,time_t t); +BOOL null_mtime(time_t mtime); void put_dos_date(char *buf,int offset,time_t unixdate); void put_dos_date2(char *buf,int offset,time_t unixdate); void put_dos_date3(char *buf,int offset,time_t unixdate); time_t make_unix_date(void *date_ptr); time_t make_unix_date2(void *date_ptr); time_t make_unix_date3(void *date_ptr); -BOOL set_filetime(char *fname,time_t mtime); char *timestring(void ); /*The following definitions come from trans2.c */ diff --git a/source/lib/system.c b/source/lib/system.c index fe8e8004d04..1486600339a 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -194,6 +194,15 @@ now for utime() ********************************************************************/ int sys_utime(char *fname,struct utimbuf *times) { + /* if the modtime is 0 or -1 then ignore the call and + return success */ + if (times->modtime == (time_t)0 || times->modtime == (time_t)-1) + return 0; + + /* if the access time is 0 or -1 then set it to the modtime */ + if (times->actime == (time_t)0 || times->actime == (time_t)-1) + times->actime = times->modtime; + return(utime(dos_to_unix(fname,False),times)); } diff --git a/source/lib/time.c b/source/lib/time.c index 4f688d2214a..ad6b04484c5 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -298,7 +298,7 @@ void put_long_date(char *p,time_t t) /**************************************************************************** check if it's a null mtime ****************************************************************************/ -static BOOL null_mtime(time_t mtime) +BOOL null_mtime(time_t mtime) { if (mtime == 0 || mtime == 0xFFFFFFFF || mtime == (time_t)-1) return(True); @@ -445,25 +445,6 @@ time_t make_unix_date3(void *date_ptr) return(t); } -/**************************************************************************** -set the time on a file -****************************************************************************/ -BOOL set_filetime(char *fname,time_t mtime) -{ - struct utimbuf times; - - if (null_mtime(mtime)) return(True); - - times.modtime = times.actime = mtime; - - if (sys_utime(fname,×)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); - } - - return(True); -} - - /**************************************************************************** return the date and time as a string ****************************************************************************/ diff --git a/source/locking/locking_shm.c b/source/locking/locking_shm.c index 99d981ed200..47074cff6bc 100644 --- a/source/locking/locking_shm.c +++ b/source/locking/locking_shm.c @@ -636,7 +636,7 @@ mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_en /******************************************************************* call the specified function on each entry under management by the -share ode system +share mode system ********************************************************************/ static int shm_share_forall(void (*fn)(share_mode_entry *, char *)) { diff --git a/source/namepacket.c b/source/namepacket.c index ba1c4044a3b..3a23806a9c4 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -626,7 +626,7 @@ BOOL listen_for_packets(BOOL run_election) * 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_interfaces_only() && (sock_array[i] == ClientNMB) && + 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", @@ -660,7 +660,7 @@ BOOL listen_for_packets(BOOL run_election) * 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_interfaces_only() && (sock_array[i] == ClientDGRAM) && + 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", diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 32fc538886a..d0dfe4ace74 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -186,7 +186,7 @@ typedef struct BOOL bUnixRealname; BOOL bNISHomeMap; BOOL bTimeServer; - BOOL bInterfacesOnly; + BOOL bBindInterfacesOnly; } global; static global Globals; @@ -273,6 +273,7 @@ typedef struct BOOL bDeleteReadonly; BOOL bFakeOplocks; BOOL bDeleteVetoFiles; + BOOL bDosFiletimes; char dummy[3]; /* for alignment */ } service; @@ -355,6 +356,7 @@ static service sDefault = False, /* bDeleteReadonly */ False, /* bFakeOplocks */ False, /* bDeleteVetoFiles */ + False, /* bDosFiletimes */ "" /* dummy */ }; @@ -414,7 +416,7 @@ struct parm_struct {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL}, {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL}, {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL}, - {"interfaces only", P_BOOL, P_GLOBAL, &Globals.bInterfacesOnly, NULL}, + {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL}, {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL}, {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL}, {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL}, @@ -577,6 +579,7 @@ struct parm_struct {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL}, {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL}, {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL}, + {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL}, {NULL, P_BOOL, P_NONE, NULL, NULL} }; @@ -669,7 +672,7 @@ static void init_globals(void) coding_system = interpret_coding_system (KANJI, SJIS_CODE); Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE; Globals.bTimeServer = False; - Globals.bInterfacesOnly = False; + Globals.bBindInterfacesOnly = False; /* these parameters are set to defaults that are more appropriate for the increasing samba install base: @@ -885,7 +888,7 @@ FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList) FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname) FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap) FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer) -FN_GLOBAL_BOOL(lp_interfaces_only,&Globals.bInterfacesOnly) +FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly) FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) @@ -973,6 +976,7 @@ FN_LOCAL_BOOL(lp_map_system,bMap_system) FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly) FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks) FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles) +FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes) FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask) FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 7576ee323b0..424c7d81832 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -789,7 +789,7 @@ int reply_setatr(char *inbuf,char *outbuf) if (check_name(fname,cnum)) ok = (dos_chmod(cnum,fname,mode,NULL) == 0); if (ok) - ok = set_filetime(fname,mtime); + ok = set_filetime(cnum,fname,mtime); if (!ok) { @@ -2270,7 +2270,7 @@ int reply_close(char *inbuf,char *outbuf) mtime = make_unix_date3(inbuf+smb_vwv1); /* try and set the date */ - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum, Files[fnum].name,mtime); close_file(fnum,True); @@ -2317,7 +2317,7 @@ int reply_writeclose(char *inbuf,char *outbuf) nwritten = write_file(fnum,data,numtowrite); - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum, Files[fnum].name,mtime); close_file(fnum,True); @@ -3787,7 +3787,7 @@ not setting timestamps of 0\n", } /* Set the date on this file */ - if(sys_utime(Files[fnum].name, &unix_times)) + if(file_utime(cnum, Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", diff --git a/source/smbd/server.c b/source/smbd/server.c index 7d9638f01e8..7639c5940be 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -254,7 +254,6 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) return(result); } - /******************************************************************* chmod a file - but preserve some bits ********************************************************************/ @@ -308,6 +307,70 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) return(sys_chmod(fname,unixmode)); } +/******************************************************************* +Wrapper around sys_utime that possibly allows DOS semantics rather +than POSIX. +*******************************************************************/ + +int file_utime(int cnum, char *fname, struct utimbuf *times) +{ + extern struct current_user current_user; + struct stat sb; + int ret = -1; + + if(sys_utime(fname, times) == 0) + return 0; + + if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum))) + return -1; + + /* We have permission (given by the Samba admin) to + break POSIX semantics and allow a user to change + the time on a file they don't own but can write to + (as DOS does). + */ + + if(sys_stat(fname,&sb) != 0) + return -1; + + /* Check if we have write access. */ + if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) + { + if (((sb.st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) + { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } + } + + return ret; +} + +/******************************************************************* +Change a filetime - possibly allowing DOS semantics. +*******************************************************************/ + +BOOL set_filetime(int cnum, char *fname, time_t mtime) +{ + struct utimbuf times; + + if (null_mtime(mtime)) return(True); + + times.modtime = times.actime = mtime; + + if (file_utime(cnum, fname, ×)) { + DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + } + + return(True); +} /**************************************************************************** check if two filenames are equal @@ -1099,13 +1162,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); */ -#if UTIME_WORKAROUND - /* XXXX - is this OK?? */ - /* this works around a utime bug but can cause other problems */ - if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) - sys_unlink(fname); -#endif - /* * Ensure we have a valid struct stat so we can search the * open fd table. diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index e484b3b2e1a..6a7fc292fae 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1433,7 +1433,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, */ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(sys_utime(fname, &tvs)!=0) + if(file_utime(cnum, fname, &tvs)!=0) { return(ERROR(ERRDOS,ERRnoaccess)); } -- cgit From c4a4a9016ea5654c5d945a935e60d4f1f3b073e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Mon, 20 Oct 1997 20:34:55 +0000 Subject: Adding make_smbcodepage.1 man page. Updated smb.conf with dos filetimes. Jeremy (jallison@whistle.com) --- docs/manpages/make_smbcodepage.1 | 131 +++++++++++++++++++++++++++++++++++++++ docs/manpages/smb.conf.5 | 18 ++++++ docs/textdocs/Support.txt | 39 +++++++++++- 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 docs/manpages/make_smbcodepage.1 diff --git a/docs/manpages/make_smbcodepage.1 b/docs/manpages/make_smbcodepage.1 new file mode 100644 index 00000000000..7c645a3a6bd --- /dev/null +++ b/docs/manpages/make_smbcodepage.1 @@ -0,0 +1,131 @@ +.TH MAKE_SMBCODEPAGE 1 make_smbcodepage make_smbcodepage +.SH NAME +make_smbcodepage \- create a binary codepage definition file from an ascii codepage definition source file, or reverse the process. +.SH SYNOPSIS +.B make_smbcodepage +.I c|d +.I codepage +.I inputfile +.I outputfile +.SH DESCRIPTION +This program is part of the Samba suite. + +.B make_smbcodepage +compiles or de-compiles codepage files for use with the internationalization +features of Samba 1.9.18. + +An ascii Samba codepage definition file is a description that tells Samba +how to map from upper to lower case for characters greater than ascii 127 +in the specified DOS code page. Note that for certain DOS codepages +(437 for example) mapping from lower to upper case may be asynchronous. +For example, in code page 437 lower case a acute maps to a plain upper +case A when going from lower to upper case, but maps from plain upper +case A to plain lower case a when lower casing a character. + +A binary Samba codepage definition file is a binary representation +of the same information, including a value that specifies what codepage +this file is describing. + +As Samba does not yet use UNICODE (current for Samba version 1.9.18) +you must specify the client code page that your DOS and Windows clients +are using if you wish to have case insensitivity done correctly for +your particular language. The default codepage Samba uses is 850 +(Western European). Ascii codepage definition sample files are provided +in the Samba distribution for codepages 437 (USA), 850 (Western European) +852 (MS-DOS Latin 2) and 932 (Kanji SJIS). Users are encouraged to +write ascii codepage definition files for their own code pages and +donate them to samba-bugs@samba.anu.edu.au. All codepage files in the +Samba source directory are compiled and installed when a 'make install' +command is issued there. + +An ascii codepage definition file consists of multiple lines containing +four fields. These fields are : +.B lower +which is the (hex) lower case character mapped on this line. +.B upper +which is the (hex) upper case character that the lower case character +will map to. +.B map upper to lower +which is a boolean value (put either True or False here) which tells +Samba if it is to map the given upper case character to the given +lower case character when lower casing a filename. +.B map lower to upper +which is a boolean value (put either True or False here) which tells +Samba if it is to map the given lower case character to the given +upper case character when upper casing a filename. + +.SH OPTIONS +.I c|d + +.RS 3 +This tells make_smbcodepage if it is compiling (c) an ascii code page file +to binary, or de-compiling a binary codepage file to ascii. +.RE + +.I codepage + +.RS 3 +This is the codepage we are processing (a number, eg. 850) +.RE + +.I inputfile + +.RS 3 +This is the input file to process. +.RE + +.I outputfile + +.RS 3 +This is the output file to produce. +.RE + +.SH FILES +.B codepage_def.<codepage> +.RS 3 +These are the input (ascii) codepage files provided in the Samba +source/ directory. +.RE +.SH FILES +.B codepage.<codepage> +.RS 3 +These are the output (binary) codepage files produced and placed in the Samba +destination lib/codepage/ directory. +.RE + +.SH ENVIRONMENT VARIABLES +Not applicable. +.SH INSTALLATION +The location of the server and its support files is a matter for individual +system administrators. The following are thus suggestions only. + +It is recommended that the +.B make_smbcodepage +program be installed under the /usr/local/samba hierarchy, in a directory readable +by all, writeable only by root. The program itself should be executable by all. +The program should NOT be setuid or setgid! +.SH VERSION +This man page is (mostly) correct for version 1.9.18 of the Samba suite, plus some +of the recent patches to it. These notes will necessarily lag behind +development of the software, so it is possible that your version of +the program has extensions or parameter semantics that differ from or are not +covered by this man page. Please notify these to the address below for +rectification. +.SH SEE ALSO +.BR smb.conf (5), +.BR smbd (8) + +.SH BUGS +None known. +.SH CREDITS +The +.B make_smbcodepage +program was written by Jeremy Allison (jallison@whistle.com) as part of the +Internationalization effort of the Samba software. + +Please send bug reports to samba-bugs@samba.anu.edu.au. + +See +.BR samba (7) +for a full list of contributors and details on how to +submit bug reports, comments etc. diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 432ef7035c3..6774e670deb 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -546,6 +546,8 @@ directory mode dont descend +dos filetimes + exec fake oplocks @@ -1264,6 +1266,22 @@ descend" entries. For example you may need "./proc" instead of just .B Example: dont descend = /proc,/dev +.SS dos filetimes (S) +Under DOS and Windows, if a user can write to a file they can change +the timestamp on it. Under POSIX semantics, only the owner of the file +or root may change the timestamp. By default, Samba runs with POSIX +semantics and refuses to change the timestamp on a file if the user +smbd is acting on behalf of is not the file owner. Setting this option +to True allows DOS semantics and smbd will change the file timstamp as +DOS requires. This is a correct implementation of a previous compile-time +options (UTIME_WORKAROUND) which was broken and is now removed. + +.B Default: + dos filetimes = False + +.B Example: + dos filetimes = True + .SS encrypt passwords (G) This boolean controls whether encrypted passwords will be negotiated diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index d482ac39123..bd1372ba208 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -33,7 +33,7 @@ Region Number of entries ASIA 1 AUSTRALIA & NEW ZEALAND 18 CANADA 8 - EUROPE 35 + EUROPE 36 MIDDLE EAST 1 AFRICA @@ -1203,6 +1203,43 @@ We provide commercial support in Belgium to large organisations (eg: N.A.T.O., Unisys, E.C.C. ...) ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +SOFIA - BULGARIA + +National Laboratory for Computer Virology and SEA Ltd. + +We work mainly in the following fields: + +* Design and testing of antivirus and computer security related software + and hardware; +* Data aquisition equipment +* Network design and consulting. + +Samba is our most common network tool for the export of data collected on +UNIX machines to PC clients, file services and simple client/server +processing schemes. + +Samba experience: Linux, Ultrix, Solaris, AIX, RiscOS. + +Client experience: LanMan, WFW, Win 95, Win NT. + +Address: + +National Laboratory for Computer Virology BAS, +Akad. G. Bonchev Str. bl.8, +Sofia 1113, +Bulgaria +E-mail:sales@nlcv.acad.bg +URL http://www.nlcv.acad.bg + +SEA Ltd, +Akad G.Bonchev Str bl. 8, rm 225, +Sofia 1113. +Bulgaria +E-mail:nmechkov@virbus.bg +URL http://www.orgchm.acad.bg/~sealtd +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ PRAHA (PRAGUE) - CZECH -- cgit From b03c6242b6d79cdca7956f689da5561302a74ae0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Mon, 20 Oct 1997 21:50:59 +0000 Subject: WHATSNEW.txt: Updated in preparation for p4. Support.txt: One more consultant. smb.conf: dos filetimes added. loadparm.c: dos filetimes added. proto.h: The usual. reply.c: dos filetimes added. server.c: dos filetimes added. time.c: dos filetimes added. trans2.c: dos filetimes added. Jeremy (jallison@whistle.com) --- WHATSNEW.txt | 53 +++++++++++++++++++++++------------ docs/manpages/smb.conf.5 | 18 ++++++++++++ docs/textdocs/Support.txt | 39 +++++++++++++++++++++++++- source/include/proto.h | 5 +++- source/lib/time.c | 21 +------------- source/param/loadparm.c | 4 +++ source/smbd/reply.c | 8 +++--- source/smbd/server.c | 71 ++++++++++++++++++++++++++++++++++++++++++----- source/smbd/trans2.c | 2 +- 9 files changed, 169 insertions(+), 52 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 3ce008ff66c..4fa0151c204 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ - WHATS NEW IN 1.9.17p2 - October 14th 1997 + WHATS NEW IN 1.9.17p4 - October 20th 1997 =========================================== -Update release: Samba - version 1.9.17p3. +Update release: Samba - version 1.9.17p4. ----------------------------------------- This is the latest stable release of Samba. This is the @@ -9,23 +9,13 @@ version that all production Samba servers should be running for all current bug-fixes. Here are a list of the fixes in this release (the fixes -introduced between 1.9.17p2 and 1.9.17p3) : +introduced between 1.9.17p3 and 1.9.17p4) : -1). Removed truncation problem with long browse lists. -2). Crash bug when dead share mode memory entries need removing. -3). Race condition in slow share mode code. -4). Potential buffer overflow from password server. -5). Fix for read-prediction growing read-only files. -6). Many quota code fixes. -7). Fix for spelling mistake in attack warning :-). -8). Removed 'ERRbaddirectory' error code - caused problem with - Visual Basic apps. -9). Allow 'hosts allow/deny' to work before client packet parsed. -10). Wrapping log file causes incorrect errors to be returned to - the clients. -11). Crash fix for nmbd Get_Hostbyname bad return. -12). 'become_root' 'unbecome_root' added to fix changing uid problems. -13). No magic scripts or printing done on exceptional file close problems. +1). Fix in nmbd for Windows 95 machines hanging on logout ! +2). Fix so nmbd ignores loopback packets. +3). New option 'dos filetimes' to fix UTIME_WORKAROUND problem. +4). Fix for nmbd ignoring WINS negative responses. +5). New PAM support from RedHat for new PAM version. Reporting bugs -------------- @@ -49,6 +39,33 @@ Regards, -------------Previous release notes------------------------- +Update release: Samba - version 1.9.17p3. +----------------------------------------- + +This is the latest stable release of Samba. This is the +version that all production Samba servers should be running +for all current bug-fixes. + +Here are a list of the fixes in this release (the fixes +introduced between 1.9.17p2 and 1.9.17p3) : + +1). Removed truncation problem with long browse lists. +2). Crash bug when dead share mode memory entries need removing. +3). Race condition in slow share mode code. +4). Potential buffer overflow from password server. +5). Fix for read-prediction growing read-only files. +6). Many quota code fixes. +7). Fix for spelling mistake in attack warning :-). +8). Removed 'ERRbaddirectory' error code - caused problem with + Visual Basic apps. +9). Allow 'hosts allow/deny' to work before client packet parsed. +10). Wrapping log file causes incorrect errors to be returned to + the clients. +11). Crash fix for nmbd Get_Hostbyname bad return. +12). 'become_root' 'unbecome_root' added to fix changing uid problems. +13). No magic scripts or printing done on exceptional file close problems. + + Security fix release: Samba - version 1.9.17p2. ---------------------------------------------- diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index b5fe0fd1a00..df63bdd55db 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -530,6 +530,8 @@ directory mode dont descend +dos filetimes + exec fake oplocks @@ -1186,6 +1188,22 @@ descend" entries. For example you may need "./proc" instead of just .B Example: dont descend = /proc,/dev +.SS dos filetimes (S) +Under DOS and Windows, if a user can write to a file they can change +the timestamp on it. Under POSIX semantics, only the owner of the file +or root may change the timestamp. By default, Samba runs with POSIX +semantics and refuses to change the timestamp on a file if the user +smbd is acting on behalf of is not the file owner. Setting this option +to True allows DOS semantics and smbd will change the file timstamp as +DOS requires. This is a correct implementation of a previous compile-time +options (UTIME_WORKAROUND) which was broken and is now removed. + +.B Default: + dos filetimes = False + +.B Example: + dos filetimes = True + .SS encrypt passwords (G) This boolean controls whether encrypted passwords will be negotiated diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index d482ac39123..bd1372ba208 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -33,7 +33,7 @@ Region Number of entries ASIA 1 AUSTRALIA & NEW ZEALAND 18 CANADA 8 - EUROPE 35 + EUROPE 36 MIDDLE EAST 1 AFRICA @@ -1203,6 +1203,43 @@ We provide commercial support in Belgium to large organisations (eg: N.A.T.O., Unisys, E.C.C. ...) ------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +SOFIA - BULGARIA + +National Laboratory for Computer Virology and SEA Ltd. + +We work mainly in the following fields: + +* Design and testing of antivirus and computer security related software + and hardware; +* Data aquisition equipment +* Network design and consulting. + +Samba is our most common network tool for the export of data collected on +UNIX machines to PC clients, file services and simple client/server +processing schemes. + +Samba experience: Linux, Ultrix, Solaris, AIX, RiscOS. + +Client experience: LanMan, WFW, Win 95, Win NT. + +Address: + +National Laboratory for Computer Virology BAS, +Akad. G. Bonchev Str. bl.8, +Sofia 1113, +Bulgaria +E-mail:sales@nlcv.acad.bg +URL http://www.nlcv.acad.bg + +SEA Ltd, +Akad G.Bonchev Str bl. 8, rm 225, +Sofia 1113. +Bulgaria +E-mail:nmechkov@virbus.bg +URL http://www.orgchm.acad.bg/~sealtd +------------------------------------------------------------------------------ + ------------------------------------------------------------------------------ PRAHA (PRAGUE) - CZECH diff --git a/source/include/proto.h b/source/include/proto.h index 718d92495fc..7717ce2d4b9 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -251,6 +251,7 @@ BOOL lp_syncalways(int ); BOOL lp_map_system(int ); BOOL lp_delete_readonly(int ); BOOL lp_fake_oplocks(int ); +BOOL lp_dos_filetimes(int ); int lp_create_mode(int ); int lp_force_create_mode(int ); int lp_dir_mode(int ); @@ -699,6 +700,8 @@ void killkids(void); mode_t unix_mode(int cnum,int dosmode); int dos_mode(int cnum,char *path,struct stat *sbuf); int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st); +int file_utime(int cnum, char *fname, struct utimbuf *times); +BOOL set_filetime(int cnum, char *fname, time_t mtime); BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path); int disk_free(char *path,int *bsize,int *dfree,int *dsize); int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); @@ -822,13 +825,13 @@ int TimeDiff(time_t t); struct tm *LocalTime(time_t *t); time_t interpret_long_date(char *p); void put_long_date(char *p,time_t t); +BOOL null_mtime(time_t mtime); void put_dos_date(char *buf,int offset,time_t unixdate); void put_dos_date2(char *buf,int offset,time_t unixdate); void put_dos_date3(char *buf,int offset,time_t unixdate); time_t make_unix_date(void *date_ptr); time_t make_unix_date2(void *date_ptr); time_t make_unix_date3(void *date_ptr); -BOOL set_filetime(char *fname,time_t mtime); char *timestring(void ); /*The following definitions come from trans2.c */ diff --git a/source/lib/time.c b/source/lib/time.c index 4f688d2214a..ad6b04484c5 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -298,7 +298,7 @@ void put_long_date(char *p,time_t t) /**************************************************************************** check if it's a null mtime ****************************************************************************/ -static BOOL null_mtime(time_t mtime) +BOOL null_mtime(time_t mtime) { if (mtime == 0 || mtime == 0xFFFFFFFF || mtime == (time_t)-1) return(True); @@ -445,25 +445,6 @@ time_t make_unix_date3(void *date_ptr) return(t); } -/**************************************************************************** -set the time on a file -****************************************************************************/ -BOOL set_filetime(char *fname,time_t mtime) -{ - struct utimbuf times; - - if (null_mtime(mtime)) return(True); - - times.modtime = times.actime = mtime; - - if (sys_utime(fname,×)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); - } - - return(True); -} - - /**************************************************************************** return the date and time as a string ****************************************************************************/ diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 90a7c9a7276..d37fc8df339 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -262,6 +262,7 @@ typedef struct BOOL *copymap; BOOL bDeleteReadonly; BOOL bFakeOplocks; + BOOL bDosFiletimes; char dummy[3]; /* for alignment */ } service; @@ -342,6 +343,7 @@ static service sDefault = NULL, /* copymap */ False, /* bDeleteReadonly */ False, /* bFakeOplocks */ + False, /* bDosFiletimes */ "" /* dummy */ }; @@ -560,6 +562,7 @@ struct parm_struct {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL}, {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL}, {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL}, + {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL}, {NULL, P_BOOL, P_NONE, NULL, NULL} }; @@ -945,6 +948,7 @@ FN_LOCAL_BOOL(lp_syncalways,bSyncAlways) FN_LOCAL_BOOL(lp_map_system,bMap_system) FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly) FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks) +FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes) FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask) FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index ffa80aac870..45acde653d9 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -753,7 +753,7 @@ int reply_setatr(char *inbuf,char *outbuf) if (check_name(fname,cnum)) ok = (dos_chmod(cnum,fname,mode,NULL) == 0); if (ok) - ok = set_filetime(fname,mtime); + ok = set_filetime(cnum,fname,mtime); if (!ok) { @@ -2188,7 +2188,7 @@ int reply_close(char *inbuf,char *outbuf) mtime = make_unix_date3(inbuf+smb_vwv1); /* try and set the date */ - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum,Files[fnum].name,mtime); close_file(fnum, 1); @@ -2235,7 +2235,7 @@ int reply_writeclose(char *inbuf,char *outbuf) nwritten = write_file(fnum,data,numtowrite); - set_filetime(Files[fnum].name,mtime); + set_filetime(cnum,Files[fnum].name,mtime); close_file(fnum, 1); @@ -3594,7 +3594,7 @@ not setting timestamps of 0\n", } /* Set the date on this file */ - if(sys_utime(Files[fnum].name, &unix_times)) + if(file_utime(cnum,Files[fnum].name, &unix_times)) return(ERROR(ERRDOS,ERRnoaccess)); DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n", diff --git a/source/smbd/server.c b/source/smbd/server.c index 3bfd5bbbf40..0c728d914ba 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -298,6 +298,70 @@ int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) return(sys_chmod(fname,unixmode)); } +/******************************************************************* +Wrapper around sys_utime that possibly allows DOS semantics rather +than POSIX. +*******************************************************************/ + +int file_utime(int cnum, char *fname, struct utimbuf *times) +{ + extern struct current_user current_user; + struct stat sb; + int ret = -1; + + if(sys_utime(fname, times) == 0) + return 0; + + if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum))) + return -1; + + /* We have permission (given by the Samba admin) to + break POSIX semantics and allow a user to change + the time on a file they don't own but can write to + (as DOS does). + */ + + if(sys_stat(fname,&sb) != 0) + return -1; + + /* Check if we have write access. */ + if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) + { + if (((sb.st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) + { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } + } + + return ret; +} + +/******************************************************************* +Change a filetime - possibly allowing DOS semantics. +*******************************************************************/ + +BOOL set_filetime(int cnum, char *fname, time_t mtime) +{ + struct utimbuf times; + + if (null_mtime(mtime)) return(True); + + times.modtime = times.actime = mtime; + + if (file_utime(cnum, fname, ×)) { + DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); + } + + return(True); +} /**************************************************************************** check if two filenames are equal @@ -1087,13 +1151,6 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); */ -#if UTIME_WORKAROUND - /* XXXX - is this OK?? */ - /* this works around a utime bug but can cause other problems */ - if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) - sys_unlink(fname); -#endif - /* * Ensure we have a valid struct stat so we can search the * open fd table. diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index f7351b99e5a..b976553a9f4 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -1383,7 +1383,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, */ if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(sys_utime(fname, &tvs)!=0) + if(file_utime(cnum,fname, &tvs)!=0) { return(ERROR(ERRDOS,ERRnoaccess)); } -- cgit From b22fa0d7e3d1158112e03f93a22232e719fe6003 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 09:09:55 +0000 Subject: add some debug info --- source/smbd/ipc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 466781c58c8..4f6c85de9f7 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2002,6 +2002,8 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); + + DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); /* check it's a supported variant */ if (strcmp(str1,"zWrLh") != 0) return False; -- cgit From ed484d4501e855f467ce2b3cfa63855acfe5e516 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 09:11:19 +0000 Subject: get rid of the KEEP_PASSWORD_SERVER_OPEN define --- source/include/local.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/include/local.h b/source/include/local.h index 97857727c74..a218dd8fc67 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -147,10 +147,6 @@ /* shall we support browse requests via a FIFO to nmbd? */ #define ENABLE_FIFO 1 -/* keep the password server open, this uses up a aocket, but is needed - by many apps */ -#define KEEP_PASSWORD_SERVER_OPEN 1 - /* how long to wait for a socket connect to happen */ #define LONG_CONNECT_TIMEOUT 30 #define SHORT_CONNECT_TIMEOUT 5 -- cgit From 3a0b5f06f42efdb522f1c5d3d9a4b4afabe03b40 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 09:12:41 +0000 Subject: This is a set of generic SMB client routines. I needed this in a hurry to fix the password server code, so I didn't use SMBlib. This code is fairly generic and uses a "struct cli_state" to hold the client state. --- source/libsmb/clientgen.c | 673 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 source/libsmb/clientgen.c diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c new file mode 100644 index 00000000000..d47c5a2755c --- /dev/null +++ b/source/libsmb/clientgen.c @@ -0,0 +1,673 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB client generic functions + Copyright (C) Andrew Tridgell 1994-1997 + + 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. +*/ + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + + +extern int DEBUGLEVEL; + +/**************************************************************************** +setup basics in a outgoing packet +****************************************************************************/ +static void cli_setup_pkt(struct cli_state *cli) +{ + SSVAL(cli->outbuf,smb_pid,cli->pid); + SSVAL(cli->outbuf,smb_uid,cli->uid); + SSVAL(cli->outbuf,smb_mid,cli->mid); + if (cli->protocol > PROTOCOL_CORE) { + SCVAL(cli->outbuf,smb_flg,0x8); + SSVAL(cli->outbuf,smb_flg2,0x1); + } +} + + +/**************************************************************************** + send a SMB trans or trans2 request + ****************************************************************************/ +static BOOL cli_send_trans(struct cli_state *cli, + int trans, char *name, int fid, int flags, + char *data,char *param,uint16 *setup, int ldata,int lparam, + int lsetup,int mdata,int mparam,int msetup) +{ + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + char *outdata,*outparam; + char *p; + + this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); + + bzero(cli->outbuf,smb_size); + set_message(cli->outbuf,14+lsetup,0,True); + CVAL(cli->outbuf,smb_com) = trans; + SSVAL(cli->outbuf,smb_tid, cli->cnum); + cli_setup_pkt(cli); + + outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); + outdata = outparam+this_lparam; + + /* primary request */ + SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ + SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ + SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */ + SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */ + SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */ + SSVAL(cli->outbuf,smb_flags,flags); /* flags */ + SIVAL(cli->outbuf,smb_timeout,0); /* timeout */ + SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */ + SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */ + SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */ + SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ + SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */ + for (i=0;i<lsetup;i++) /* setup[] */ + SSVAL(cli->outbuf,smb_setup+i*SIZEOFWORD,setup[i]); + p = smb_buf(cli->outbuf); + if (trans==SMBtrans) { + strcpy(p,name); /* name[] */ + } else { + *p++ = 0; /* put in a null smb_name */ + *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */ + } + if (this_lparam) /* param[] */ + memcpy(outparam,param,this_lparam); + if (this_ldata) /* data[] */ + memcpy(outdata,data,this_ldata); + set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */ + PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + + show_msg(cli->outbuf); + send_smb(cli->fd,cli->outbuf); + + if (this_ldata < ldata || this_lparam < lparam) { + /* receive interim response */ + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout) || + CVAL(cli->inbuf,smb_rcls) != 0) { + return(False); + } + + tot_data = this_ldata; + tot_param = this_lparam; + + while (tot_data < ldata || tot_param < lparam) { + this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */ + this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam)); + + set_message(cli->outbuf,trans==SMBtrans?8:9,0,True); + CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2; + + outparam = smb_buf(cli->outbuf); + outdata = outparam+this_lparam; + + /* secondary request */ + SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ + SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ + SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */ + SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */ + SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */ + SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */ + SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ + SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */ + if (trans==SMBtrans2) + SSVAL(cli->outbuf,smb_sfid,fid); /* fid */ + if (this_lparam) /* param[] */ + memcpy(outparam,param,this_lparam); + if (this_ldata) /* data[] */ + memcpy(outdata,data,this_ldata); + set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ + PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + + show_msg(cli->outbuf); + send_smb(cli->fd,cli->outbuf); + + tot_data += this_ldata; + tot_param += this_lparam; + } + } + + return(True); +} + + +/**************************************************************************** + receive a SMB trans or trans2 response allocating the necessary memory + ****************************************************************************/ +static BOOL cli_receive_trans(struct cli_state *cli, + int trans,int *data_len, + int *param_len, char **data,char **param) +{ + int total_data=0; + int total_param=0; + int this_data,this_param; + + *data_len = *param_len = 0; + + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + show_msg(cli->inbuf); + + /* sanity check */ + if (CVAL(cli->inbuf,smb_com) != trans) { + DEBUG(0,("Expected %s response, got command 0x%02x\n", + trans==SMBtrans?"SMBtrans":"SMBtrans2", + CVAL(cli->inbuf,smb_com))); + return(False); + } + if (CVAL(cli->inbuf,smb_rcls) != 0) + return(False); + + /* parse out the lengths */ + total_data = SVAL(cli->inbuf,smb_tdrcnt); + total_param = SVAL(cli->inbuf,smb_tprcnt); + + /* allocate it */ + *data = Realloc(*data,total_data); + *param = Realloc(*param,total_param); + + while (1) { + this_data = SVAL(cli->inbuf,smb_drcnt); + this_param = SVAL(cli->inbuf,smb_prcnt); + + if (this_data + *data_len > total_data || + this_param + *param_len > total_param) { + DEBUG(1,("Data overflow in cli_receive_trans\n")); + return False; + } + + if (this_data) + memcpy(*data + SVAL(cli->inbuf,smb_drdisp), + smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff), + this_data); + if (this_param) + memcpy(*param + SVAL(cli->inbuf,smb_prdisp), + smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff), + this_param); + *data_len += this_data; + *param_len += this_param; + + /* parse out the total lengths again - they can shrink! */ + total_data = SVAL(cli->inbuf,smb_tdrcnt); + total_param = SVAL(cli->inbuf,smb_tprcnt); + + if (total_data <= *data_len && total_param <= *param_len) + break; + + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + show_msg(cli->inbuf); + + /* sanity check */ + if (CVAL(cli->inbuf,smb_com) != trans) { + DEBUG(0,("Expected %s response, got command 0x%02x\n", + trans==SMBtrans?"SMBtrans":"SMBtrans2", + CVAL(cli->inbuf,smb_com))); + return(False); + } + if (CVAL(cli->inbuf,smb_rcls) != 0) + return(False); + } + + return(True); +} + + +/**************************************************************************** +call a remote api +****************************************************************************/ +static BOOL cli_api(struct cli_state *cli, + int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, + int *rdrcnt, char *param,char *data, + char **rparam, char **rdata) +{ + cli_send_trans(cli,SMBtrans,"\\PIPE\\LANMAN",0,0, + data,param,NULL, + drcnt,prcnt,0, + mdrcnt,mprcnt,0); + + return (cli_receive_trans(cli,SMBtrans, + rdrcnt,rprcnt, + rdata,rparam)); +} + + +/**************************************************************************** +perform a NetWkstaUserLogon +****************************************************************************/ +BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) +{ + char *rparam = NULL; + char *rdata = NULL; + char *p; + int rdrcnt,rprcnt; + pstring param; + + memset(param, 0, sizeof(param)); + + /* send a SMBtrans command with api NetWkstaUserLogon */ + p = param; + SSVAL(p,0,132); /* api number */ + p += 2; + strcpy(p,"OOWb54WrLh"); + p = skip_string(p,1); + strcpy(p,"WB21BWDWWDDDDDDDzzzD"); + p = skip_string(p,1); + SSVAL(p,0,1); + p += 2; + strcpy(p,user); + strupper(p); + p += 21; p++; p += 15; p++; + strcpy(p, workstation); + strupper(p); + p += 16; + SSVAL(p, 0, BUFFER_SIZE); + p += 2; + SSVAL(p, 0, BUFFER_SIZE); + p += 2; + + cli->error = -1; + + if (cli_api(cli, PTR_DIFF(p,param),0, + 1024,BUFFER_SIZE, + &rprcnt,&rdrcnt, + param,NULL, + &rparam,&rdata)) { + cli->error = SVAL(rparam,0); + p = rdata; + + if (cli->error == 0) { + DEBUG(4,("NetWkstaUserLogon success\n")); + cli->privilages = SVAL(p, 24); + fstrcpy(cli->eff_name,p+2); + } else { + DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->error)); + } + } + + if (rparam) free(rparam); + if (rdata) free(rdata); + return cli->error == 0; +} + + + +static struct { + int prot; + char *name; + } +prots[] = + { + {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, + {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, + {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, + {PROTOCOL_LANMAN1,"LANMAN1.0"}, + {PROTOCOL_LANMAN2,"LM1.2X002"}, + {PROTOCOL_LANMAN2,"Samba"}, + {PROTOCOL_NT1,"NT LM 0.12"}, + {PROTOCOL_NT1,"NT LANMAN 1.0"}, + {-1,NULL} + }; + + +/**************************************************************************** +send a session setup +****************************************************************************/ +BOOL cli_session_setup(struct cli_state *cli, + char *user, + char *pass, int passlen, + char *ntpass, int ntpasslen, + char *workgroup) +{ + char *p; + fstring pword; + + if (cli->protocol < PROTOCOL_LANMAN1) + return False; + + if (passlen > sizeof(pword)-1) { + return False; + } + + if ((cli->sec_mode & 2) && *pass && passlen != 24) { + passlen = 24; + SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword); + } else { + memcpy(pword, pass, passlen); + } + + /* if in share level security then don't send a password now */ + if (!(cli->sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} + + /* send a session setup command */ + bzero(cli->outbuf,smb_size); + + if (cli->protocol < PROTOCOL_NT1) { + set_message(cli->outbuf,10,1 + strlen(user) + passlen,True); + CVAL(cli->outbuf,smb_com) = SMBsesssetupX; + cli_setup_pkt(cli); + + CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit); + SSVAL(cli->outbuf,smb_vwv3,2); + SSVAL(cli->outbuf,smb_vwv4,1); + SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); + SSVAL(cli->outbuf,smb_vwv7,passlen); + p = smb_buf(cli->outbuf); + memcpy(p,pword,passlen); + p += passlen; + strcpy(p,user); + strupper(p); + } else { + set_message(cli->outbuf,13,0,True); + CVAL(cli->outbuf,smb_com) = SMBsesssetupX; + cli_setup_pkt(cli); + + CVAL(cli->outbuf,smb_vwv0) = 0xFF; + SSVAL(cli->outbuf,smb_vwv2,BUFFER_SIZE); + SSVAL(cli->outbuf,smb_vwv3,2); + SSVAL(cli->outbuf,smb_vwv4,cli->pid); + SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); + SSVAL(cli->outbuf,smb_vwv7,passlen); + SSVAL(cli->outbuf,smb_vwv8,ntpasslen); + p = smb_buf(cli->outbuf); + memcpy(p,pword,passlen); + p += SVAL(cli->outbuf,smb_vwv7); + memcpy(p,ntpass,ntpasslen); + p += SVAL(cli->outbuf,smb_vwv8); + strcpy(p,user); + strupper(p); + p = skip_string(p,1); + strcpy(p,workgroup); + strupper(p); + p = skip_string(p,1); + strcpy(p,"Unix");p = skip_string(p,1); + strcpy(p,"Samba");p = skip_string(p,1); + set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False); + } + + send_smb(cli->fd,cli->outbuf); + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + show_msg(cli->inbuf); + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return False; + } + + /* use the returned uid from now on */ + cli->uid = SVAL(cli->inbuf,smb_uid); + + return True; +} + + +/**************************************************************************** +send a tconX +****************************************************************************/ +BOOL cli_send_tconX(struct cli_state *cli, + char *share, char *dev, char *pword, int passlen) +{ + char *p; + bzero(cli->outbuf,smb_size); + bzero(cli->inbuf,smb_size); + + set_message(cli->outbuf,4, + 2 + strlen(share) + passlen + strlen(dev),True); + CVAL(cli->outbuf,smb_com) = SMBtconX; + cli_setup_pkt(cli); + + SSVAL(cli->outbuf,smb_vwv0,0xFF); + SSVAL(cli->outbuf,smb_vwv3,passlen); + + p = smb_buf(cli->outbuf); + memcpy(p,pword,passlen); + p += passlen; + strcpy(p,share); + p = skip_string(p,1); + strcpy(p,dev); + + SCVAL(cli->inbuf,smb_rcls, 1); + + send_smb(cli->fd,cli->outbuf); + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + if (CVAL(cli->inbuf,smb_rcls) != 0) { + return False; + } + + cli->cnum = SVAL(cli->inbuf,smb_tid); + return True; +} + + +/**************************************************************************** +send a tree disconnect +****************************************************************************/ +BOOL cli_tdis(struct cli_state *cli) +{ + bzero(cli->outbuf,smb_size); + set_message(cli->outbuf,0,0,True); + CVAL(cli->outbuf,smb_com) = SMBtdis; + SSVAL(cli->outbuf,smb_tid,cli->cnum); + cli_setup_pkt(cli); + + send_smb(cli->fd,cli->outbuf); + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + return CVAL(cli->inbuf,smb_rcls) == 0; +} + + +/**************************************************************************** +send a negprot command +****************************************************************************/ +BOOL cli_negprot(struct cli_state *cli) +{ + char *p; + int numprots; + int plength; + + bzero(cli->outbuf,smb_size); + + /* setup the protocol strings */ + for (plength=0,numprots=0; + prots[numprots].name && prots[numprots].prot<=cli->protocol; + numprots++) + plength += strlen(prots[numprots].name)+2; + + set_message(cli->outbuf,0,plength,True); + + p = smb_buf(cli->outbuf); + for (numprots=0; + prots[numprots].name && prots[numprots].prot<=cli->protocol; + numprots++) { + *p++ = 2; + strcpy(p,prots[numprots].name); + p += strlen(p) + 1; + } + + CVAL(cli->outbuf,smb_com) = SMBnegprot; + cli_setup_pkt(cli); + + CVAL(smb_buf(cli->outbuf),0) = 2; + + send_smb(cli->fd,cli->outbuf); + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + show_msg(cli->inbuf); + + if (CVAL(cli->inbuf,smb_rcls) != 0 || + ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) { + return(False); + } + + cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; + + + if (cli->protocol < PROTOCOL_NT1) { + cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); + cli->max_xmit = SVAL(cli->inbuf,smb_vwv2); + cli->sesskey = IVAL(cli->inbuf,smb_vwv6); + cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60; + /* this time is converted to GMT by make_unix_date */ + cli->servertime = make_unix_date(cli->inbuf+smb_vwv8); + if (cli->protocol >= PROTOCOL_COREPLUS) { + cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0); + cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0); + } + memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); + } else { + /* NT protocol */ + cli->sec_mode = CVAL(cli->inbuf,smb_vwv1); + cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1); + cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1); + cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60; + /* this time arrives in real GMT */ + cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1); + memcpy(cli->cryptkey,smb_buf(cli->inbuf),8); + if (IVAL(cli->inbuf,smb_vwv9+1) & 1) + cli->readbraw_supported = + cli->writebraw_supported = True; + } + + return True; +} + + +/**************************************************************************** + send a session request +****************************************************************************/ +BOOL cli_session_request(struct cli_state *cli, char *host, int name_type, + char *myname) +{ + fstring dest; + char *p; + int len = 4; + /* send a session request (RFC 1002) */ + + fstrcpy(dest,host); + + p = strchr(dest,'.'); + if (p) *p = 0; + + fstrcpy(cli->desthost, dest); + + /* put in the destination name */ + p = cli->outbuf+len; + name_mangle(dest,p,name_type); + len += name_len(p); + + /* and my name */ + p = cli->outbuf+len; + name_mangle(myname,p,0); + len += name_len(p); + + /* setup the packet length */ + _smb_setlen(cli->outbuf,len); + CVAL(cli->outbuf,0) = 0x81; + + send_smb(cli->fd,cli->outbuf); + DEBUG(5,("Sent session request\n")); + + if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) + return False; + + if (CVAL(cli->inbuf,0) != 0x82) { + cli->error = CVAL(cli->inbuf,0); + return False; + } + return(True); +} + + +/**************************************************************************** +open the client sockets +****************************************************************************/ +BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip) +{ + struct in_addr dest_ip; + + fstrcpy(cli->desthost, host); + + if (!ip) { + struct hostent *hp; + + if ((hp = Get_Hostbyname(cli->desthost)) == 0) { + return False; + } + + putip((char *)&dest_ip,(char *)hp->h_addr); + } else { + dest_ip = *ip; + } + + + cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout); + if (cli->fd == -1) + return False; + + return True; +} + + +/**************************************************************************** +initialise a client structure +****************************************************************************/ +BOOL cli_initialise(struct cli_state *cli) +{ + if (cli->initialised) cli_shutdown(cli); + + memset(cli, 0, sizeof(*cli)); + cli->fd = -1; + cli->cnum = -1; + cli->pid = getpid(); + cli->mid = 1; + cli->uid = getuid(); + cli->protocol = PROTOCOL_NT1; + cli->timeout = 20000; + cli->bufsize = 0x10000; + cli->max_xmit = cli->bufsize - 4; + cli->outbuf = (char *)malloc(cli->bufsize); + cli->inbuf = (char *)malloc(cli->bufsize); + if (!cli->outbuf || !cli->inbuf) return False; + cli->initialised = 1; + return True; +} + +/**************************************************************************** +shutdown a client structure +****************************************************************************/ +void cli_shutdown(struct cli_state *cli) +{ + if (cli->outbuf) free(cli->outbuf); + if (cli->inbuf) free(cli->inbuf); + if (cli->fd != -1) close(cli->fd); + memset(cli, 0, sizeof(*cli)); +} -- cgit From 9caab6bec07230ecc80aada0881f6978f28c58a8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 10:09:30 +0000 Subject: add the new password server code to the 1.9.17 tree. This needed to be fixed as the previous code could provide a security hole if the NT server was misconfigured --- source/client/client.c | 13 ++- source/client/clientutil.c | 65 ++++++----- source/include/local.h | 4 - source/include/proto.h | 35 ++++-- source/include/smb.h | 27 +++++ source/smbd/ipc.c | 2 + source/smbd/password.c | 279 ++++++++++++++++++--------------------------- source/smbd/reply.c | 11 +- source/smbd/server.c | 170 +++++++++++++-------------- 9 files changed, 297 insertions(+), 309 deletions(-) diff --git a/source/client/client.c b/source/client/client.c index cd9e8d1c97c..a48d1b4990b 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -3411,6 +3411,13 @@ static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setu uid = SVAL(inbuf,smb_uid); } + if (SVAL(inbuf, smb_vwv2) & 1) + DEBUG(1,("connected as guest ")); + if (sec_mode & 1) + DEBUG(1,("security=user\n")); + else + DEBUG(1,("security=share\n")); + /* now we've got a connection - send a tcon message */ bzero(outbuf,smb_size); @@ -3520,6 +3527,7 @@ static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setu free(inbuf); free(outbuf); } + return True; } @@ -3693,6 +3701,7 @@ static BOOL send_trans_request(char *outbuf,int trans, return(True); } + /**************************************************************************** try and browse available connections on a host ****************************************************************************/ @@ -4118,7 +4127,7 @@ static BOOL open_sockets(int port ) strcpy(desthost,host); } - if (*myname == 0) { + if (!(*myname)) { get_myname(myname,NULL); } strupper(myname); @@ -4639,7 +4648,7 @@ static void usage(char *pname) strcpy(workgroup,lp_workgroup()); load_interfaces(); - get_myname(*myname?NULL:myname,NULL); + get_myname((*myname)?NULL:myname,NULL); strupper(myname); if (tar_type) { diff --git a/source/client/clientutil.c b/source/client/clientutil.c index 1b59946ff5b..cb0a731480c 100644 --- a/source/client/clientutil.c +++ b/source/client/clientutil.c @@ -77,7 +77,7 @@ extern int Client; /**************************************************************************** setup basics in a outgoing packet ****************************************************************************/ -void cli_setup_pkt(char *outbuf) +static void cli_setup_pkt(char *outbuf) { SSVAL(outbuf,smb_pid,pid); SSVAL(outbuf,smb_uid,uid); @@ -89,11 +89,14 @@ void cli_setup_pkt(char *outbuf) } } + + /**************************************************************************** receive a SMB trans or trans2 response allocating the necessary memory ****************************************************************************/ -BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, - int *param_len, char **data,char **param) +static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, + int *param_len, char **data, + char **param) { int total_data=0; int total_param=0; @@ -164,7 +167,7 @@ BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, /**************************************************************************** send a session request ****************************************************************************/ -BOOL cli_send_session_request(char *inbuf, char *outbuf) +static BOOL cli_send_session_request(char *inbuf, char *outbuf) { fstring dest; char *p; @@ -661,35 +664,12 @@ void cli_send_logout(void) } - -/**************************************************************************** -call a remote api -****************************************************************************/ -BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, - int *rdrcnt, char *param,char *data, char **rparam,char **rdata) -{ - static char *inbuf=NULL; - static char *outbuf=NULL; - - if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, - data,param,NULL, - drcnt,prcnt,0, - mdrcnt,mprcnt,0); - - return (cli_receive_trans_response(inbuf,SMBtrans, - rdrcnt,rprcnt, - rdata,rparam)); -} - /**************************************************************************** send a SMB trans or trans2 request ****************************************************************************/ -BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags, - char *data,char *param,uint16 *setup, int ldata,int lparam, - int lsetup,int mdata,int mparam,int msetup) +static BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags, + char *data,char *param,uint16 *setup, int ldata,int lparam, + int lsetup,int mdata,int mparam,int msetup) { int i; int this_ldata,this_lparam; @@ -797,6 +777,31 @@ BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int fl } + +/**************************************************************************** +call a remote api +****************************************************************************/ +BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, + int *rdrcnt, char *param,char *data, + char **rparam, char **rdata) +{ + static char *inbuf=NULL; + static char *outbuf=NULL; + + if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + + cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, + data,param,NULL, + drcnt,prcnt,0, + mdrcnt,mprcnt,0); + + return (cli_receive_trans_response(inbuf,SMBtrans, + rdrcnt,rprcnt, + rdata,rparam)); +} + + /**************************************************************************** open the client sockets ****************************************************************************/ diff --git a/source/include/local.h b/source/include/local.h index f5f2c318180..92d566cf82d 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -147,10 +147,6 @@ /* shall we support browse requests via a FIFO to nmbd? */ #define ENABLE_FIFO 1 -/* keep the password server open, this uses up a aocket, but is needed - by many apps */ -#define KEEP_PASSWORD_SERVER_OPEN 1 - /* how long to wait for a socket connect to happen */ #define LONG_CONNECT_TIMEOUT 30 #define SHORT_CONNECT_TIMEOUT 5 diff --git a/source/include/proto.h b/source/include/proto.h index 7717ce2d4b9..e9776bf2548 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -32,19 +32,31 @@ void cmd_help(void); BOOL reopen_connection(char *inbuf,char *outbuf); char *smb_errstr(char *inbuf); +/*The following definitions come from clientgen.c */ + +BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation); +BOOL cli_session_setup(struct cli_state *cli, + char *user, + char *pass, int passlen, + char *ntpass, int ntpasslen, + char *workgroup); +BOOL cli_send_tconX(struct cli_state *cli, + char *share, char *dev, char *pword, int passlen); +BOOL cli_tdis(struct cli_state *cli); +BOOL cli_negprot(struct cli_state *cli); +BOOL cli_session_request(struct cli_state *cli, char *host, int name_type, + char *myname); +BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip); +BOOL cli_initialise(struct cli_state *cli); +void cli_shutdown(struct cli_state *cli); + /*The following definitions come from clientutil.c */ -void cli_setup_pkt(char *outbuf); -BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, - int *param_len, char **data,char **param); -BOOL cli_send_session_request(char *inbuf, char *outbuf); BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup); void cli_send_logout(void); BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, - int *rdrcnt, char *param,char *data, char **rparam,char **rdata); -BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags, - char *data,char *param,uint16 *setup, int ldata,int lparam, - int lsetup,int mdata,int mparam,int msetup); + int *rdrcnt, char *param,char *data, + char **rparam, char **rdata); BOOL cli_open_sockets(int port); BOOL cli_reopen_connection(char *inbuf,char *outbuf); char *smb_errstr(char *inbuf); @@ -585,8 +597,11 @@ BOOL user_ok(char *user,int snum); BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL *guest,BOOL *force,uint16 vuid); BOOL check_hosts_equiv(char *user); -BOOL server_cryptkey(char *buf); -BOOL server_validate(char *buf); +struct cli_state *server_client(void); +struct cli_state *server_cryptkey(void); +BOOL server_validate(char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen); /*The following definitions come from pcap.c */ diff --git a/source/include/smb.h b/source/include/smb.h index b55c180f361..a273d962b69 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -261,6 +261,33 @@ struct smb_passwd { }; +struct cli_state { + int fd; + int cnum; + int pid; + int mid; + int uid; + int protocol; + int sec_mode; + int error; + int privilages; + fstring eff_name; + fstring desthost; + char cryptkey[8]; + uint32 sesskey; + int serverzone; + uint32 servertime; + int readbraw_supported; + int writebraw_supported; + int timeout; + int max_xmit; + char *outbuf; + char *inbuf; + int bufsize; + int initialised; +}; + + struct current_user { int cnum, id; int uid, gid; diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 1d7ee375d3f..c63a54c2ac2 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -2004,6 +2004,8 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); + + DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); /* check it's a supported variant */ if (strcmp(str1,"zWrLh") != 0) return False; diff --git a/source/smbd/password.c b/source/smbd/password.c index 68205b4dae9..0d9db08dd98 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -1507,207 +1507,146 @@ BOOL check_hosts_equiv(char *user) return(False); } - -int password_client = -1; -static fstring pserver; -static char *secserver_inbuf = NULL; +static struct cli_state cli; /**************************************************************************** -attempted support for server level security +return the client state structure ****************************************************************************/ -BOOL server_cryptkey(char *buf) +struct cli_state *server_client(void) { - pstring outbuf; - fstring pass_protocol; - extern fstring remote_machine; - char *p; - int len; - fstring desthost; - struct in_addr dest_ip; - int port = SMB_PORT; - BOOL ret; - - if(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n")); - return False; - } - } - - if (password_client >= 0) - close(password_client); - password_client = -1; - - if (Protocol < PROTOCOL_NT1) { - strcpy(pass_protocol,"LM1.2X002"); - } else { - strcpy(pass_protocol,"NT LM 0.12"); - } - - bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - bzero(outbuf,sizeof(outbuf)); - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - strcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); - if (password_client >= 0) { - DEBUG(3,("connected to password server %s\n",p)); - StrnCpy(pserver,p,sizeof(pserver)-1); - break; - } - } - - if (password_client < 0) { - DEBUG(1,("password server not available\n")); - return(False); - } - - - /* send a session request (RFC 8002) */ - - /* put in the destination name */ - len = 4; - p = outbuf+len; - name_mangle(desthost,p,' '); - len += name_len(p); - p = outbuf+len; - - /* and my name */ - /* Fix from Frank Varnavas <varnavas@ny.ubs.com>. - We cannot use the same name as the client to - the NT password server, as NT will drop client - connections if the same client name connects - twice. Instead, synthesize a name from our pid. - and the remote machine name. - */ - { - char buf[32]; /* create name as PIDname */ - sprintf(buf,"%d", getpid()); - strncpy(&buf[strlen(buf)], remote_machine, 31 - strlen(buf)); - buf[31] = '\0'; - DEBUG(1,("negprot w/password server as %s\n",buf)); - name_mangle(buf,p,' '); - len += name_len(p); - } - - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(password_client,outbuf); - - - if (!receive_smb(password_client,secserver_inbuf,5000) || - CVAL(secserver_inbuf,0) != 0x82) { - DEBUG(1,("%s rejected the session\n",pserver)); - close(password_client); password_client = -1; - return(False); - } + return &cli; +} - DEBUG(3,("got session\n")); +/**************************************************************************** +support for server level security +****************************************************************************/ +struct cli_state *server_cryptkey(void) +{ + fstring desthost; + struct in_addr dest_ip; + extern fstring local_machine; + char *p; + + if (!cli_initialise(&cli)) + return NULL; + + for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { + fstrcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + if (zero_ip(dest_ip)) { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } - bzero(outbuf,smb_size); + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",p)); + continue; + } - /* setup the protocol string */ - set_message(outbuf,0,strlen(pass_protocol)+2,True); - p = smb_buf(outbuf); - *p++ = 2; - strcpy(p,pass_protocol); + if (cli_connect(&cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",p)); + break; + } + } - CVAL(outbuf,smb_com) = SMBnegprot; - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); + if (!p) { + DEBUG(1,("password server not available\n")); + cli_shutdown(&cli); + return NULL; + } - send_smb(password_client,outbuf); - ret = receive_smb(password_client,secserver_inbuf,5000); + if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { + DEBUG(1,("%s rejected the session\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) { - DEBUG(1,("%s rejected the protocol\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + DEBUG(3,("got session\n")); - if (!(CVAL(secserver_inbuf,smb_vwv1) & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + if (!cli_negprot(&cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4); + if (cli.protocol < PROTOCOL_LANMAN2 || + !(cli.sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - DEBUG(3,("password server OK\n")); + DEBUG(3,("password server OK\n")); - return(True); + return &cli; } /**************************************************************************** -attempted support for server level security +validate a password with the password server ****************************************************************************/ -BOOL server_validate(char *buf) +BOOL server_validate(char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) { - pstring outbuf; - BOOL ret; + extern fstring local_machine; + fstring share; - if(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_validate: malloc fail for input buffer.\n")); - return False; - } - } + if (!cli.initialised) { + DEBUG(1,("password server %s is not connected\n", cli.desthost)); + return(False); + } - if (password_client < 0) { - DEBUG(1,("%s not connected\n",pserver)); - return(False); - } + if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli.desthost)); + return False; + } - bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - memcpy(outbuf,buf,sizeof(outbuf)); + /* if logged in as guest then reject */ + if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); + return(False); + } - /* send a session setup command */ - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); - CVAL(outbuf,smb_vwv0) = 0xFF; - set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); + sprintf(share,"\\\\%s\\IPC$", cli.desthost); - SCVAL(secserver_inbuf,smb_rcls,1); + if (!cli_send_tconX(&cli, share, "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); + return False; + } - send_smb(password_client,outbuf); - ret = receive_smb(password_client,secserver_inbuf,5000); - if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) { - DEBUG(1,("password server %s rejected the password\n",pserver)); - return(False); - } + if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); + cli_tdis(&cli); + return False; + } - /* if logged in as guest then reject */ - if ((SVAL(secserver_inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n",pserver)); - return(False); - } + if (cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); + cli_tdis(&cli); + return False; + } - DEBUG(3,("password server %s accepted the password\n",pserver)); + if (!strequal(cli.eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + cli.desthost, + cli.eff_name)); + cli_tdis(&cli); + return False; + } -#if !KEEP_PASSWORD_SERVER_OPEN - close(password_client); password_client= -1; -#endif + DEBUG(3,("password server %s accepted the password\n", cli.desthost)); - return(True); + cli_tdis(&cli); + + return(True); } + + + diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 45acde653d9..0cb43a6fb70 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -377,8 +377,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL computer_id=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); + char *domain = ""; *smb_apasswd = 0; + *smb_ntpasswd = 0; smb_bufsize = SVAL(inbuf,smb_vwv2); smb_mpxmax = SVAL(inbuf,smb_vwv3); @@ -467,8 +469,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) p += passlen1 + passlen2; fstrcpy(user,p); p = skip_string(p,1); + domain = p; + DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - p,skip_string(p,1),skip_string(p,2))); + domain,skip_string(p,1),skip_string(p,2))); } @@ -508,7 +512,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) guest = True; - if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && + if (!guest && !(lp_security() == SEC_SERVER && + server_validate(user, domain, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen)) && !check_hosts_equiv(user)) { diff --git a/source/smbd/server.c b/source/smbd/server.c index 0c728d914ba..0eaa708520f 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -2222,22 +2222,21 @@ static int sig_cld() **************************************************************************/ static int sig_pipe() { - extern int password_client; - BlockSignals(True,SIGPIPE); + struct cli_state *cli; + BlockSignals(True,SIGPIPE); - if (password_client != -1) { - DEBUG(3,("lost connection to password server\n")); - close(password_client); - password_client = -1; + if ((cli = server_client()) && cli->initialised) { + DEBUG(3,("lost connection to password server\n")); + cli_shutdown(cli); #ifndef DONT_REINSTALL_SIG - signal(SIGPIPE, SIGNAL_CAST sig_pipe); + signal(SIGPIPE, SIGNAL_CAST sig_pipe); #endif - BlockSignals(False,SIGPIPE); - return 0; - } + BlockSignals(False,SIGPIPE); + return 0; + } - exit_server("Got sigpipe\n"); - return(0); + exit_server("Got sigpipe\n"); + return(0); } /**************************************************************************** @@ -2892,11 +2891,6 @@ int reply_lanman1(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; @@ -2911,15 +2905,7 @@ int reply_lanman1(char *outbuf) Protocol = PROTOCOL_LANMAN1; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD - if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif - } - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ SSVAL(outbuf,smb_vwv4,1); @@ -2943,36 +2929,45 @@ int reply_lanman2(char *outbuf) int secword=0; BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } if (lp_security()>=SEC_USER) secword |= 1; if (doencrypt) secword |= 2; - set_message(outbuf,13,doencrypt?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); + if (doencrypt) { + crypt_len = 8; + if (!cli) { #ifdef SMB_PASSWD - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - generate_next_challenge(smb_buf(outbuf)); + generate_next_challenge(cryptkey); #endif + } else { + memcpy(cryptkey, cli->cryptkey, 8); +#ifdef SMB_PASSWD + set_challenge(cli->cryptkey); +#endif + } + } + set_message(outbuf,13,doencrypt?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,getpid()); + if (doencrypt) + memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_LANMAN2; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD - if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif - } - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv2,max_recv); SSVAL(outbuf,smb_vwv3,lp_maxmux()); SSVAL(outbuf,smb_vwv4,1); @@ -3002,13 +2997,32 @@ int reply_nt1(char *outbuf) BOOL doencrypt = SMBENCRYPT(); time_t t = time(NULL); int data_len; - int encrypt_len; - char challenge_len = 8; - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); + struct cli_state *cli = NULL; + char cryptkey[8]; + char crypt_len = 0; + + if (lp_security() == SEC_SERVER) { + cli = server_cryptkey(); + } + + if (cli) { + DEBUG(3,("using password server validation\n")); + doencrypt = ((cli->sec_mode & 2) != 0); + } + + if (doencrypt) { + crypt_len = 8; + if (!cli) { +#ifdef SMB_PASSWD + generate_next_challenge(cryptkey); +#endif + } else { + memcpy(cryptkey, cli->cryptkey, 8); +#ifdef SMB_PASSWD + set_challenge(cli->cryptkey); +#endif + } + } if (lp_readraw() && lp_writeraw()) { @@ -3021,44 +3035,18 @@ int reply_nt1(char *outbuf) /* decide where (if) to put the encryption challenge, and follow it with the OEM'd domain name */ - encrypt_len = doencrypt?challenge_len:0; -#if UNICODE - data_len = encrypt_len + 2*(strlen(myworkgroup)+1); -#else - data_len = encrypt_len + strlen(myworkgroup) + 1; -#endif + data_len = crypt_len + strlen(myworkgroup) + 1; set_message(outbuf,17,data_len,True); - -#if UNICODE - /* put the OEM'd domain name */ - PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup); -#else - strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup); -#endif + strcpy(smb_buf(outbuf)+crypt_len, myworkgroup); CVAL(outbuf,smb_vwv1) = secword; -#ifdef SMB_PASSWD - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - { - generate_next_challenge(smb_buf(outbuf)); - - /* Tell the nt machine how long the challenge is. */ - SSVALS(outbuf,smb_vwv16+1,challenge_len); - } -#endif + SSVALS(outbuf,smb_vwv16+1,crypt_len); + if (doencrypt) + memcpy(smb_buf(outbuf), cryptkey, 8); Protocol = PROTOCOL_NT1; - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); -#ifdef SMB_PASSWD - if (doencrypt) set_challenge(smb_buf(outbuf)); -#endif - } - - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ @@ -4127,16 +4115,16 @@ static void process(void) } if (keepalive && (counter-last_keepalive)>keepalive) { - extern int password_client; - if (!send_keepalive(Client)) { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (password_client != -1) - send_keepalive(password_client); - last_keepalive = counter; + struct cli_state *cli = server_client(); + if (!send_keepalive(Client)) { + DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + return; + } + /* also send a keepalive to the password server if its still + connected */ + if (cli && cli->initialised) + send_keepalive(cli->fd); + last_keepalive = counter; } /* check for connection timeouts */ -- cgit From 3d6328e1a1ad59fe31aa2071885ad12ce488ba23 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 10:12:28 +0000 Subject: update the password server docs --- docs/manpages/smb.conf.5 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index df63bdd55db..a491f8fa08b 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -2355,6 +2355,11 @@ If you list several hosts in the "password server" option then smbd will try each in turn till it finds one that responds. This is useful in case your primary server goes down. +If you are using a WindowsNT server as your password server then you +will have to ensure that your users are able to login from the Samba +server, as the network logon will appear to come from there rather +than from the users workstation. + .SS path (S) A synonym for this parameter is 'directory'. -- cgit From 3990b10bcc84e96fe34162fe2c42b674fbb96430 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 10:31:44 +0000 Subject: add a note on how to map usernames with spaces in them --- docs/manpages/smb.conf.5 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index a491f8fa08b..1e66ccb44c4 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -3230,6 +3230,14 @@ would use You can have as many mappings as you like in a username map file. +You can map Windows usernames that have spaces in them by using double +quotes around the name. For example: + + tridge = "Andrew Tridgell" + +would map the windows username "Andrew Tridgell" to the unix username +tridge. + Note that the remapping is applied to all occurrences of usernames. Thus if you connect to "\e\eserver\efred" and "fred" is remapped to "mary" then you will actually be connecting to -- cgit From e7ac7935e842738802434edca120bd772ca16fa8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 10:46:01 +0000 Subject: add the generic client code to 1.9.17 --- source/libsmb/clientgen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index d47c5a2755c..d50349501fe 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -352,8 +352,10 @@ BOOL cli_session_setup(struct cli_state *cli, } if ((cli->sec_mode & 2) && *pass && passlen != 24) { +#ifdef SMB_PASSWD passlen = 24; SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword); +#endif } else { memcpy(pword, pass, passlen); } -- cgit From 51b435abde1e7a30f9d1fa4b8c41b7935b86f90c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 11:57:13 +0000 Subject: fix the order of become_uid() and become_gid() in become_root(). This was a harmless bug but left log entries --- source/smbd/uid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/uid.c b/source/smbd/uid.c index fe2cb5a652d..db1e5e94c3b 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -505,8 +505,8 @@ void become_root(int save_dir) current_user_saved = current_user; become_root_depth = 1; - become_gid(0); become_uid(0); + become_gid(0); } /**************************************************************************** -- cgit From e7e832a47104f69cc4842b14b355f8cfbab9c343 Mon Sep 17 00:00:00 2001 From: Paul Blackman <ictinus@samba.org> Date: Tue, 21 Oct 1997 12:09:34 +0000 Subject: Updated Support entry. Hmm.. I thought I removed samba.faq in this branch before. --- docs/samba.faq | 900 ---------------------------------------------- docs/textdocs/Support.txt | 5 +- 2 files changed, 1 insertion(+), 904 deletions(-) delete mode 100644 docs/samba.faq diff --git a/docs/samba.faq b/docs/samba.faq deleted file mode 100644 index 19126439500..00000000000 --- a/docs/samba.faq +++ /dev/null @@ -1,900 +0,0 @@ - - Frequently Asked Questions - - about the - - SAMBA Suite - - (FAQ version 1.9.15a, Samba version 1.09.15) - -------------------------------------------------------------------------------- - -This FAQ was originally prepared by Karl Auer and is -currently maintained by Paul Blackman (ictinus@lake.canberra.edu.au). - -As Karl originally said, 'this FAQ was prepared with lots of help from numerous -net.helpers', and that's the way I'd like to keep it. So if you find anything -that you think should be in here don't hesitate to contact me. - -Thanks to Karl for the work he's done, and continuing thanks to Andrew Tridgell -for developing Samba. - -Note: This FAQ is (and probably always will be) under construction. Some -sections exist only as optimistic entries in the Contents page. - -------------------------------------------------------------------------------- - -Contents - - * SECTION ONE: General information - All about Samba - what it is, how to get it, related sources of - information, how to understand the version numbering scheme, - pizza details - * SECTION TWO: Compiling and installing Samba on a Unix host - Common problems that arise when building and installing Samba under - Unix. - * SECTION THREE: Common client problems - Common problems that arise when trying to communicate from a client - computer to a Samba server. All problems which have symptoms you see - at the client end will be in this section. - * SECTION FOUR: Specific client problems - This section covers problems that are specific to certain clients, - such as Windows for Workgroups or Windows NT. Please check Section - Three first! - * SECTION FIVE: Specific client application problems - This section covers problems that are specific to certain products, - such as Windows for Workgroups or Windows NT. Please check Sections - Three and Four first! - * SECTION SIX: Miscellaneous - All the questions that aren't classifiable into any other section. - - -=============================================================================== -SECTION ONE: General information -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: What is Samba? - -Samba is a suite of programs which work together to allow clients to access -to a server's filespace and printers via the SMB (Session Message Block) -protocol. Initially written for Unix, Samba now also runs on Netware, OS/2 and -AmigaDOS. - -In practice, this means that you can redirect disks and printers to Unix disks -and printers from Lan Manager clients, Windows for Workgroups 3.11 clients, -Windows NT clients, Linux clients and OS/2 clients. There is also a generic -Unix client program supplied as part of the suite which allows Unix users to -use an ftp-like interface to access filespace and printers on any other SMB -servers. This gives the capability for these operating systems to behave much -like a LAN Server or Windows NT Server machine, only with added functionality -and flexibility designed to make life easier for administrators. - -The components of the suite are (in summary): - - * smbd, the SMB server. This handles actual connections from clients, - doing all the file, permission and username work - * nmbd, the Netbios name server, which helps clients locate servers, - doing the browsing work and managing domains as this capability is - being built into Samba - * smbclient, the Unix-hosted client program - * smbrun, a little 'glue' program to help the server run external - programs - * testprns, a program to test server access to printers - * testparms, a program to test the Samba configuration file for - correctness - * smb.conf, the Samba configuration file - * smbprint, a sample script to allow a Unix host to use smbclient to - print to an SMB server - * documentation! DON'T neglect to read it - you will save a great deal - of time! - -The suite is supplied with full source (of course!) and is GPLed. - -The primary creator of the Samba suite is Andrew Tridgell. Later versions -incorporate much effort by many net.helpers. The man pages and this FAQ were -originally written by Karl Auer. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: What is the current version of Samba? - -At time of writing, the current version was 1.9.16. If you want to be sure -check the bottom of the change-log file. -(ftp://samba.anu.edu.au/pub/samba/alpha/change-log) - -For more information see question 5, "What do the version numbers mean?" - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: Where can I get it? - -The Samba suite is available via anonymous ftp from samba.anu.edu.au. The -latest and greatest versions of the suite are in the directory: - -/pub/samba/ - -Development (read "alpha") versions, which are NOT necessarily stable and which -do NOT necessarily have accurate documentation, are available in the directory: - -/pub/samba/alpha - -Note that binaries are NOT included in any of the above. Samba is distributed -ONLY in source form, though binaries may be available from other sites. Recent -versions of some Linux distributions, for example, do contain Samba binaries -for that platform. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: What do the version numbers mean? - -It is not recommended that you run a version of Samba with the word "alpha" -in its name unless you know what you are doing and are willing to do some -debugging. Many, many people just get the latest recommended stable release -version and are happy. If you are brave, by all means take the plunge and -help with the testing and development - but don't install it on your -departmental server. Samba is typically very stable and safe, and this is -mostly due to the policy of many public releases. - -How the scheme works: - -1) when major changes are made the version number is increased. For example, -the transition from 1.9.15 to 1.9.16. However, this version number will not -appear immediately and people should continue to use 1.9.15 for production -systems (see next point.) - -2) just after major changes are made the software is considered -unstable, and a series of alpha releases are distributed, for example -1.9.16alpha1. These are for testing by those who know what they are doing. -The "alpha" in the filename will hopefully scare off those who are just -looking for the latest version to install. - -3) when Andrew thinks that the alphas have stabilised to the point where he -would recommend new users install it, he renames it to the same version -number without the alpha, for example 1.9.16. - -4) inevitably bugs are found in the "stable" releases and minor -patch levels are released which give us the pXX series, for example -1.9.16p2. - -So the progression goes: - - 1.9.15p7 (production) - 1.9.15p8 (production) - 1.9.16alpha1 (test sites only) - : - 1.9.16alpha20 (test sites only) - 1.9.16 (production) - 1.9.16p1 (production) - -The above system means that whenever someone looks at the samba ftp site -they will be able to grab the highest numbered release without an -alpha in the name and be sure of getting the current recommended -version. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: What platforms are supported? - -Many different platforms have run Samba successfully. The platforms most widely -used and thus best tested are Linux and SunOS. - -At time of writing, the Makefile claimed support for: - - * SunOS - * Linux with shadow passwords - * Linux without shadow passwords - * SOLARIS - * SOLARIS 2.2 and above (aka SunOS 5) - * SVR4 - * ULTRIX - * OSF1 (alpha only) - * OSF1 with NIS and Fast Crypt (alpha only) - * OSF1 V2.0 Enhanced Security (alpha only) - * AIX - * BSDI - * NetBSD - * NetBSD 1.0 - * SEQUENT - * HP-UX - * SGI - * SGI IRIX 4.x.x - * SGI IRIX 5.x.x - * FreeBSD - * NeXT 3.2 and above - * NeXT OS 2.x - * NeXT OS 3.0 - * ISC SVR3V4 (POSIX mode) - * ISC SVR3V4 (iBCS2 mode) - * A/UX 3.0 - * SCO with shadow passwords. - * SCO with shadow passwords, without YP. - * SCO with TCB passwords - * SCO 3.2v2 (ODT 1.1) with TCP passwords - * intergraph - * DGUX - * Apollo Domain/OS sr10.3 (BSD4.3) - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: How can I find out more about Samba? - -There are two mailing lists devoted to discussion of Samba-related matters. -There is also the newsgroup, comp.protocols.smb, which has a great deal of -discussion on Samba. There is also a WWW site 'SAMBA Web Pages' at -http://samba.canberra.edu.au/pub/samba/samba.html, under which there is a -comprehensive survey of Samba users. Another useful resource is the hypertext -archive of the Samba mailing list. - -Send email to listproc@samba.anu.edu.au. Make sure the subject line is -blank, and include the following two lines in the body of the message: - - subscribe samba Firstname Lastname - subscribe samba-announce Firstname Lastname - -Obviously you should substitute YOUR first name for "Firstname" and YOUR last -name for "Lastname"! Try not to send any signature stuff, it sometimes confuses -the list processor. - -The samba list is a digest list - every eight hours or so it regurgitates a -single message containing all the messages that have been received by the list -since the last time and sends a copy of this message to all subscribers. - -If you stop being interested in Samba, please send another email to -listproc@samba.anu.edu.au. Make sure the subject line is blank, and -include the following two lines in the body of the message: - - unsubscribe samba - unsubscribe samba-announce - -The From: line in your message MUST be the same address you used when you -subscribed. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: Something's gone wrong - what should I do? - -[#] *** IMPORTANT! *** [#] -DO NOT post messages on mailing lists or in newsgroups until you have carried -out the first three steps given here! - -Firstly, see if there are any likely looking entries in this FAQ! If you have -just installed Samba, have you run through the checklist in DIAGNOSIS.txt? It -can save you a lot of time and effort. - -Secondly, read the man pages for smbd, nmbd and smb.conf, looking for topics -that relate to what you are trying to do. - -Thirdly, if there is no obvious solution to hand, try to get a look at the log -files for smbd and/or nmbd for the period during which you were having -problems. You may need to reconfigure the servers to provide more extensive -debugging information - usually level 2 or level 3 provide ample debugging -info. Inspect these logs closely, looking particularly for the string "Error:". - -Fourthly, if you still haven't got anywhere, ask the mailing list or newsgroup. -In general nobody minds answering questions provided you have followed the -preceding steps. It might be a good idea to scan the archives of the mailing -list, which are available through the Samba web site described in the previous -section. - -If you successfully solve a problem, please mail the FAQ maintainer a succinct -description of the symptom, the problem and the solution, so I can incorporate -it in the next version. - -If you make changes to the source code, _please_ submit these patches so that -everyone else gets the benefit of your work. This is one of the most important -aspects to the maintainence of Samba. Send all patches to -samba-bugs@samba.anu.edu.au, not Andrew Tridgell or any other individual and -not the samba team mailing list. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* n: Pizza Supply Details - -Those who have registered in the Samba survey as "Pizza Factory" will already -know this, but the rest may need some help. Andrew doesn't ask for payment, -but he does appreciate it when people give him pizza. This calls for a little -organisation when the pizza donor is twenty thousand kilometres away, but -it has been done. - -Method 1: Ring up your local branch of an international pizza chain and see if -they honour their vouchers internationally. Pizza Hut do, which is how the -entire Canberra Linux Users Group got to eat pizza one night, courtesy of -someone in the US - -Method 2: Ring up a local pizza shop in Canberra and quote a credit card -number for a certain amount, and tell them that Andrew will be collecting -it (don't forget to tell him.) One kind soul from Germany did this. - -Method 3: Purchase a pizza voucher from your local pizza shop that has no -international affiliations and send it to Andrew. It is completely useless -but he can hang it on the wall next to the one he already has from Germany :-) - -Method 4: Air freight him a pizza with your favourite regional flavours. It will -probably get stuck in customs or torn apart by hungry sniffer dogs but it will -have been a noble gesture. - -=============================================================================== -SECTION TWO: Compiling and installing Samba on a Unix host -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -=============================================================================== -SECTION THREE: Common client problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: I can't see the Samba server in any browse lists! - -*** Until the FAQ can be updated, please check the file: -*** ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt -*** for more information on browsing. - -If your GUI client does not permit you to select non-browsable servers, you may -need to do so on the command line. For example, under Lan Manager you might -connect to the above service as disk drive M: thusly: - - net use M: \\mary\fred - -The details of how to do this and the specific syntax varies from client to -client - check your client's documentation. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: Some files that I KNOW are on the server doesn't show up when I view the - directories from my client! - -If you check what files are not showing up, you will note that they are files -which contain upper case letters or which are otherwise not DOS-compatible (ie, -they are not legal DOS filenames for some reason). - -The Samba server can be configured either to ignore such files completely, or -to present them to the client in "mangled" form. If you are not seeing the -files at all, the Samba server has most likely been configured to ignore them. -Consult the man page smb.conf(5) for details of how to change this - the -parameter you need to set is "mangled names = yes". - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: Some files on the server show up with really wierd filenames when I view -the directories from my client! - -If you check what files are showing up wierd, you will note that they are files -which contain upper case letters or which are otherwise not DOS-compatible (ie, -they are not legal DOS filenames for some reason). - -The Samba server can be configured either to ignore such files completely, or -to present them to the client in "mangled" form. If you are seeing strange file -names, they are most likely "mangled". If you would prefer to have such files -ignored rather than presented in "mangled" form, consult the man page -smb.conf(5) for details of how to change the server configuration - the -parameter you need to set is "mangled names = no". - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: My client reports "cannot locate specified computer" or similar. - -This indicates one of three things: You supplied an incorrect server name, the -underlying TCP/IP layer is not working correctly, or the name you specified -cannot be resolved. - -After carefully checking that the name you typed is the name you should have -typed, try doing things like pinging a host or telnetting to somewhere on your -network to see if TCP/IP is functioning OK. If it is, the problem is most -likely name resolution. - -If your client has a facility to do so, hardcode a mapping between the hosts IP -and the name you want to use. For example, with Man Manager or Windows for -Workgroups you would put a suitable entry in the file LMHOSTS. If this works, -the problem is in the communication between your client and the netbios name -server. If it does not work, then there is something fundamental wrong with -your naming and the solution is beyond the scope of this document. - -If you do not have any server on your subnet supplying netbios name resolution, -hardcoded mappings are your only option. If you DO have a netbios name server -running (such as the Samba suite's nmbd program), the problem probably lies in -the way it is set up. Refer to Section Two of this FAQ for more ideas. - -By the way, remember to REMOVE the hardcoded mapping before further tests :-) - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: My client reports "cannot locate specified share name" or similar. - -This message indicates that your client CAN locate the specified server, which -is a good start, but that it cannot find a service of the name you gave. - -The first step is to check the exact name of the service you are trying to -connect to (consult your system administrator). Assuming it exists and you -specified it correctly (read your client's doco on how to specify a service -name correctly), read on: - - * Many clients cannot accept or use service names longer than eight - characters. - * Many clients cannot accept or use service names containing spaces. - * Some servers (not Samba though) are case sensitive with service names. - * Some clients force service names into upper case. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: My client reports "cannot find domain controller", "cannot log on to the -network" or similar. - -Nothing is wrong - Samba does not implement the primary domain name controller -stuff for several reasons, including the fact that the whole concept of a -primary domain controller and "logging in to a network" doesn't fit well with -clients possibly running on multiuser machines (such as users of smbclient -under Unix). Having said that, several developers are working hard on -building it in to the next major version of Samba. If you can contribute, -send a message to samba-bugs! - -Seeing this message should not affect your ability to mount redirected disks -and printers, which is really what all this is about. - -For many clients (including Windows for Workgroups and Lan Manager), setting -the domain to STANDALONE at least gets rid of the message. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 7: Printing doesn't work :-( - -Make sure that the specified print command for the service you are connecting -to is correct and that it has a fully-qualified path (eg., use "/usr/bin/lpr" -rather than just "lpr"). - -Make sure that the spool directory specified for the service is writable by the -user connected to the service. In particular the user "nobody" often has -problems with printing, even if it worked with an earlier version of Samba. Try -creating another guest user other than "nobody". - -Make sure that the user specified in the service is permitted to use the -printer. - -Check the debug log produced by smbd. Search for the printer name and see if -the log turns up any clues. Note that error messages to do with a service ipc$ -are meaningless - they relate to the way the client attempts to retrieve status -information when using the LANMAN1 protocol. - -If using WfWg then you need to set the default protocol to TCP/IP, not Netbeui. -This is a WfWg bug. - -If using the Lanman1 protocol (the default) then try switching to coreplus. -Also not that print status error messages don't mean printing won't work. The -print status is received by a different mechanism. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 8: My programs install on the server OK, but refuse to work properly. - -There are numerous possible reasons for this, but one MAJOR possibility is that -your software uses locking. Make sure you are using Samba 1.6.11 or later. It -may also be possible to work around the problem by setting "locking=no" in the -Samba configuration file for the service the software is installed on. This -should be regarded as a strictly temporary solution. - -In earlier Samba versions there were some difficulties with the very latest -Microsoft products, particularly Excel 5 and Word for Windows 6. These should -have all been solved. If not then please let Andrew Tridgell know. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 9: My "server string" doesn't seem to be recognized, my client reports the - default setting, eg. "Samba 1.9.15p4", instead of what I have changed it - to in the smb.conf file. - -You need to use the -C option in nmbd. The "server string" affects -what smbd puts out and -C affects what nmbd puts out. In a future -version these will probably be combined and -C will be removed, but -for now use -C - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 10: When I attempt to get a listing of available resources from the Samba - server, my client reports - "This server is not configured to list shared resources". - -Your guest account is probably invalid for some reason. Samba uses -the guest account for browsing in smbd. Check that your guest account is -valid. - -See also 'guest account' in smb.conf man page. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 11: You get the message "you appear to have a trapdoor uid system" - in your logs - -This can have several causes. It might be because you are using a uid -or gid of 65535 or -1. This is a VERY bad idea, and is a big security -hole. Check carefully in your /etc/passwd file and make sure that no -user has uid 65535 or -1. Especially check the "nobody" user, as many -broken systems are shipped with nobody setup with a uid of 65535. - -It might also mean that your OS has a trapdoor uid/gid system :-) - -This means that once a process changes effective uid from root to -another user it can't go back to root. Unfortunately Samba relies on -being able to change effective uid from root to non-root and back -again to implement its security policy. If your OS has a trapdoor uid -system this won't work, and several things in Samba may break. Less -things will break if you use user or server level security instead of -the default share level security, but you may still strike -problems. - -The problems don't give rise to any security holes, so don't panic, -but it does mean some of Samba's capabilities will be unavailable. -In particular you will not be able to connect to the Samba server as -two different uids at once. This may happen if you try to print as a -"guest" while accessing a share as a normal user. It may also affect -your ability to list the available shares as this is normally done as -the guest user. - -Complain to your OS vendor and ask them to fix their system. - -Note: the reason why 65535 is a VERY bad choice of uid and gid is that -it casts to -1 as a uid, and the setreuid() system call ignores (with -no error) uid changes to -1. This means any daemon attempting to run -as uid 65535 will actually run as root. This is not good! - -=============================================================================== -SECTION FOUR: Specific client problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: Are any MacIntosh clients for Samba. - -Yes. Thursby Software Systems have released 'Dave' - a SMB client for -MacIntosh systems. This is a commercial product and inclusion in this -faq does not imply any endorsement by the Samba developers. Having said -that, the first public demonstration of 'Dave' was to the Samba server -run by Andrew Tridgell over the Internet from Redmond, Washington, USA to -Australia as part of the first CIFS developers conference. - -For more details on 'Dave' contact : - -Web contact: www.thursby.com - -Thursby Software Systems, Inc. -5840 W. Interstate 20 -Arlington, Texas 76017 U.S.A. -Voice: 817-478-5070 -FAX: 817-561-2313 -sales@thursby.com - -There are currently no Free Software solutions other than to make -your UNIX server talk AppleTalk. - -In Rob Newberry's words (rob@eats.com, Sun, 4 Dec 1994): - -In future Apple System Software, you may see support for other protocols, such -as SMB -- Applet is working on a new networking architecture that will make it -easier to support additional protocols. But it's not here yet. - -If you want your Unix machine to speak Appletalk, there are several options. -"Netatalk" and "CAP" are free, and available on the net. There are also -several commercial options, such as "PacerShare" and "Helios" (I think). -In any case, you'll have to look around for a server, not anything for the Mac. - -Depending on your OS, some of these may not help you. I am currently -coordinating the effort to get CAP working with Native Ethertalk under Linux, -but we're not done yet. - -Rob - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 2: I am getting a "Session request failed (131,130)" error when I try to - connect to my Win95 PC with smbclient. I am able to connect from the PC - to the Samba server without problems. What gives? - -The following answer is provided by John E. Miller: - -I'll assume that you're able to ping back and forth between the machines by -IP address and name, and that you're using some security model where you're -confident that you've got user IDs and passwords right. The logging options -(-d3 or greater) can help a lot with that. DNS and WINS configuration can -also impact connectivity as well. - -Now, on to 'scope id's. Somewhere in your Win95 TCP/IP network configuration -(I'm too much of an NT bigot to know where it's located in the Win95 setup, -but I'll have to learn someday since I teach for a Microsoft Solution Provider -Authorized Tech Education Center - what an acronym...) [Note: It's under -Control Panel | Network | TCP/IP | WINS Configuration] there's a little text -entry field called something like 'Scope ID'. - -This field essentially creates 'invisible' sub-workgroups on the same wire. -Boxes can only see other boxes whose Scope IDs are set to the exact same -value - it's sometimes used by OEMs to configure their boxes to browse only -other boxes from the same vendor and, in most environments, this field should -be left blank. If you, in fact, have something in this box that EXACT value -(case-sensitive!) needs to be provided to smbclient and nmbd as the -i -(lowercase) parameter. So, if your Scope ID is configured as the string -'SomeStr' in Win95 then you'd have to use smbclient -iSomeStr <otherparms> -in connecting to it. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 3: How do I synchronize my PC's clock with my Samba server? - -To syncronize your PC's clock with your Samba server: - -* Copy timesync.pif to your windows directory - * timesync.pif can be found at: - http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif -* Add timesync.pif to your 'Start Up' group/folder -* Open the properties dialog box for the program/icon - * Make sure the 'Run Minimized' option is set in program 'Properties' - * Change the command line section that reads \\sambahost to reflect the name - of your server. -* Close the properties dialog box by choosing 'OK' - -Each time you start your computer (or login for Win95) your PC will -synchronize its clock with your Samba server. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 4: Problems with WinDD, NTrigue, WinCenterPro etc - -All of the above programs are applications that sit on an NT box and -allow multiple users to access the NT GUI applications from remote -workstations (often over X). - -What has this got to do with Samba? The problem comes when these users -use filemanager to mount shares from a Samba server. The most common -symptom is that the first user to connect get correct file permissions -and has a nice day, but subsequent connections get logged in as the -same user as the first person to login. They find that they cannot -access files in their own home directory, but that they can access -files in the first users home directory (maybe not such a nice day -after all?) - -Why does this happen? The above products all share a common heritage -(and code base I believe). They all open just a single TCP based SMB -connection to the Samba server, and requests from all users are piped -over this connection. This is unfortunate, but not fatal. - -It means that if you run your Samba server in share level security -(the default) then things will definately break as described above. The -share level SMB security model has no provision for multiple user IDs -on the one SMB connection. See security_level.txt in the docs for more -info on share/user/server level security. - -If you run in user or server level security then you have a chance, -but only if you have a recent version of Samba (at least 1.9.15p6). In -older versions bugs in Samba meant you still would have had problems. - -If you have a trapdoor uid system in your OS then it will never work -properly. Samba needs to be able to switch uids on the connection and -it can't if your OS has a trapdoor uid system. You'll know this -because Samba will note it in your logs. - -Also note that you should not use the magic "homes" share name with -products like these, as otherwise all users will end up with the same -home directory. Use \\server\username instead. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 5: Problem with printers under NT - -This info from Stefan Hergeth may be useful: - - A network-printer (with ethernetcard) is connected to the NT-Clients via - our UNIX-Fileserver (SAMBA-Server), like the configuration told by - Matthew Harrell <harrell@leech.nrl.navy.mil> (see WinNT.txt) - - 1.) If a user has choosen this printer as the default printer in his - NT-Session and this printer is not connected to the network - (e.g. switched off) than this user has a problem with the SAMBA- - connection of his filesystems. It's very slow. - - 2.) If the printer is connected to the network everything works fine. - - 3.) When the smbd ist started with debug level 3, you can see that the - NT spooling system try to connect to the printer many times. If the - printer ist not connected to the network this request fails and the - NT spooler is wasting a lot of time to connect to the printer service. - This seems to be the reason for the slow network connection. - - 4.) Maybe it's possible to change this behaviour by setting different printer - properties in the Print-Manager-Menu of NT, but i didn't try it - yet. - - I hope this information will help in some way. - - Stefan Hergeth <hergeth@f7axp1.informatik.fh-muenchen.de> - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 6: Why are my file's timestamps off by an hour, or by a few hours? - -This is from Paul Eggert <eggert@twinsun.com>. - -Most likely it's a problem with your time zone settings. - -Internally, Samba maintains time in traditional Unix format, -namely, the number of seconds since 1970-01-01 00:00:00 Universal Time -(or ``GMT''), not counting leap seconds. - -On the server side, Samba uses the Unix TZ variable to convert internal -timestamps to and from local time. So on the server side, there are two -things to get right. - - 1. The Unix system clock must have the correct Universal time. - Use the shell command "sh -c 'TZ=UTC0 date'" to check this. - - 2. The TZ environment variable must be set on the server - before Samba is invoked. The details of this depend on the - server OS, but typically you must edit a file whose name is - /etc/TIMEZONE or /etc/default/init, or run the command `zic -l'. - - 3. TZ must have the correct value. - - 3a. If possible, use geographical time zone settings - (e.g. TZ='America/Los_Angeles' or perhaps - TZ=':US/Pacific'). These are supported by most - popular Unix OSes, are easier to get right, and are - more accurate for historical timestamps. If your - operating system has out-of-date tables, you should be - able to update them from the public domain time zone - tables at <URL:ftp://elsie.nci.nih.gov/pub/>. - - 3b. If your system does not support geographical time zone - settings, you must use a Posix-style TZ strings, e.g. - TZ='PST8PDT,M4.1.0/2,M10.5.0/2' for US Pacific time. - Posix TZ strings can take the following form (with optional - items in brackets): - - StdOffset[Dst[Offset],Date/Time,Date/Time] - - where: - - `Std' is the standard time designation (e.g. `PST'). - - `Offset' is the number of hours behind UTC (e.g. `8'). - Prepend a `-' if you are ahead of UTC, and - append `:30' if you are at a half-hour offset. - Omit all the remaining items if you do not use - daylight-saving time. - - `Dst' is the daylight-saving time designation - (e.g. `PDT'). - - The optional second `Offset' is the number of - hours that daylight-saving time is behind UTC. - The default is 1 hour ahead of standard time. - - `Date/Time,Date/Time' specify when daylight-saving - time starts and ends. The format for a date is - `Mm.n.d', which specifies the dth day (0 is Sunday) - of the nth week of the mth month, where week 5 means - the last such day in the month. The format for a - time is [h]h[:mm[:ss]], using a 24-hour clock. - - Other Posix string formats are allowed but you don't want - to know about them. - -On the client side, you must make sure that your client's clock and -time zone is also set appropriately. [[I don't know how to do this.]] - -Samba traditionally has had many problems dealing with time zones, due -to the bizarre ways that Microsoft network protocols handle time -zones. A common symptom is for file timestamps to be off by an hour. -To work around the problem, try disconnecting from your Samba server -and then reconnecting to it; or upgrade your Samba server to -1.9.16alpha10 or later. - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 7: How do I set the printer driver name correctly? - -Question: -> On NT, I opened "Printer Manager" and "Connect to Printer". -> Enter "\\ptdi270\ps1" in the box of printer. I got the -> following error message: -> -> You do not have sufficient access to your machine -> to connect to the selected printer, since a driver -> needs to be installed locally. - -Answer: - -In the more recent versions of Samba you can now set the "printer -driver" in smb.conf. This tells the client what driver to use. For -example, I have: - - printer driver = HP LaserJet 4L - -and NT knows to use the right driver. You have to get this string -exactly right. - -To find the exact string to use, you need to get to the dialog box in -your client where you select which printer driver to install. The -correct strings for all the different printers are shown in a listbox -in that dialog box. - -You could also try setting the driver to NULL like this: - - printer driver = NULL - -this is effectively what older versions of Samba did, so if that -worked for you then give it a go. If this does work then let me know -and I'll make it the default. Currently the default is a 0 length -string. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* 8: I have upgraded my NT 4.0 system to service pack 3. Why - can't I connect anymore ? - -This is not a bug. Microsoft has changed their policy on sending -unencrypted passwords over the net. They no longer default to allowing -unencrypted passwords to be sent over the net. This effects all Samba -servers which are configured to use security=share or security=user level -security without password encryption. They do, however, have a fix which -can be applied to the registry to fix the problem. Here's a synopsis -from the SP3 web page that discusses how to enable unencrypted password -sending from an NT 4.0 box. - -A better solution is to re-compile Samba to use encrypted passwords. -See the document : - -ftp://samba.anu.edu.au/pub/samba/docs/ENCRYPTION.txt - ->SYMPTOMS ->========== -> ->Connecting to SMB servers (such as Samba) with unencrypted password fails -after upgrading to Windows NT 4.0 service pack 3 version 1.76. -> ->CAUSE ->====== -> ->The SMB redirector in Windows NT 4.0 service pack 3 version 1.76 handles ->unencrypted passwords differently than previous version of Windows NT. ->Beginning with this version, the SMB redirector will not send an ->unencrypted password unless you add a registry entry to enable them. -> ->RESOLUTION ->=========== -> ->To enable unencrypted (plain text) passwords modify the registry in this way. -> -> -> ->WARNING: Using Registry Editor incorrectly can cause serious, system-wide ->problems that may require you to reinstall Windows NT to correct them. ->Microsoft cannot guarantee that any problems resulting from the use of ->Registry Editor can be solved. Use this tool at your own risk. -> -> -> ->1. Run Registry Editor (REGEDT32.EXE). -> ->2. From the HKEY_LOCAL_MACHINE subtree, go to the following key: -> -> -> ->\system\currentcontrolset\services\rdr\parameters -> -> -> ->3. From the Edit menu, select Add Value. -> ->4. Add the following: -> -> -> ->Value Name: EnablePlainTextPassword -> ->Data Type: REG_DWORD -> ->Data: 1 -> -> -> ->5. Choose OK and quit Registry Editor. -> ->6. Shutdown and restart Windows NT. -> -> ------------------------------------------------------------------------ - -=============================================================================== -SECTION FIVE: Specific client application problems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* 1: MS Office Setup reports "Cannot change properties of the file named: - X:\MSOFFICE\SETUP.INI" - -When installing MS Office on a Samba drive for which you have admin user -permissions, ie. admin users = <username>, you will find the setup program -unable to complete the installation. - -To get around this problem, do the installation without admin user permissions -The problem is that MS Office Setup checks that a file is rdonly by trying to -open it for writing. - -Admin users can always open a file for writing, as they run as root. -You just have to install as a non-admin user and then use "chown -R" to fix -the owner. - -=============================================================================== -SECTION SIX: Miscellaneous -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Maintained By Paul Blackman, Email:ictinus@lake.canberra.edu.au diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index bd1372ba208..ee8e1b6befa 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -61,13 +61,10 @@ For futher information, please consult our website www.obsidian.co.za JOHANNESBURG - SOUTH AFRICA Company: Symphony Research (Pty) Ltd - Contact: Dr Evan Summers, <evan@sr.co.za>, cell 082 900-8632. + Contact: Dr Evan Summers, <evan@sr.co.za>, tel 011 728-5742. keywords: Samba on Linux, support and consulting Johannesburg (South Africa) -Evan Summers, PhD Tel +27 82 900-8632 Symphony -Linux systems integration http://sr.co.za Research -Johannesburg, South Africa mailto:evan@sr.co.za (Pty)Ltd ------------------------------------------------------------------------------ -- cgit From 608683e62d7f2cfe490757888951e4845d49ca21 Mon Sep 17 00:00:00 2001 From: Paul Blackman <ictinus@samba.org> Date: Tue, 21 Oct 1997 12:22:11 +0000 Subject: Update 1.9.17 branch with faq docs from 1.9.18 I don't think I've clobbered anything I shouldn't have. --- docs/faq/Samba-Server-FAQ.html | 2 +- docs/faq/Samba-Server-FAQ.sgml | 6 +- docs/faq/Samba-meta-FAQ-2.html | 2 +- docs/faq/Samba-meta-FAQ.html | 2 +- docs/faq/Samba-meta-FAQ.sgml | 8 +- docs/faq/Samba-meta-FAQ.txt | 437 ++++++++++++++++++++++++++++++----------- docs/faq/sambafaq-1.html | 2 +- docs/faq/sambafaq-3.html | 2 +- docs/faq/sambafaq.html | 2 +- docs/faq/sambafaq.sgml | 11 +- docs/faq/sambafaq.txt | 314 ++++++++++++++--------------- 11 files changed, 499 insertions(+), 289 deletions(-) diff --git a/docs/faq/Samba-Server-FAQ.html b/docs/faq/Samba-Server-FAQ.html index 501ff1b1ed8..eadc3e26ede 100644 --- a/docs/faq/Samba-Server-FAQ.html +++ b/docs/faq/Samba-Server-FAQ.html @@ -39,7 +39,7 @@ Table of Contents <HR> <H1> Samba Server FAQ</H1> -<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.1, 23 Aug '97 +<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.3, 7 Oct '97 <P><HR><EM> This is the <EM>Server</EM> Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. A general diff --git a/docs/faq/Samba-Server-FAQ.sgml b/docs/faq/Samba-Server-FAQ.sgml index 4887481e2b1..020d5322811 100644 --- a/docs/faq/Samba-Server-FAQ.sgml +++ b/docs/faq/Samba-Server-FAQ.sgml @@ -3,7 +3,7 @@ v 0.1 23 Aug 1997 Dan Shearer Original Samba-Client-FAQ.sgml from Paul's sambafaq.sgml v 0.2 25 Aug 1997 Dan - + v 0.3 7 Oct 1997 Paul, changed email address from ictinus@lake... to ictinus@samba.anu --> @@ -11,9 +11,9 @@ <title> Samba Server FAQ -<author>Dan Shearer & Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Dan Shearer & Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.1, 23 Aug '97 +<date>v 0.3, 7 Oct '97 <abstract> This is the <em>Server</em> Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server diff --git a/docs/faq/Samba-meta-FAQ-2.html b/docs/faq/Samba-meta-FAQ-2.html index c5ebab7e7e4..ac760380067 100644 --- a/docs/faq/Samba-meta-FAQ-2.html +++ b/docs/faq/Samba-meta-FAQ-2.html @@ -166,7 +166,7 @@ See below for subscription information. discussion about Samba. </LI> <LI>The WWW site 'SAMBA Web Pages' at -<A HREF="http://samba.canberra.edu.au/pub/samba/samba.html">http://samba.canberra.edu.au/pub/samba/samba.html</A> includes: +<A HREF="http://samba.anu.edu.au/samba/">http://samba.anu.edu.au/samba/</A> includes: <UL> <LI>Links to man pages and documentation, including this FAQ</LI> diff --git a/docs/faq/Samba-meta-FAQ.html b/docs/faq/Samba-meta-FAQ.html index 7821083740d..5a70808867b 100644 --- a/docs/faq/Samba-meta-FAQ.html +++ b/docs/faq/Samba-meta-FAQ.html @@ -37,7 +37,7 @@ Table of Contents <HR> <H1> Samba meta FAQ</H1> -<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.1, 23 Aug '97 +<H2>Dan Shearer & Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.3, 7 Oct '97 <P><HR><EM> This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It contains overview information for the Samba suite of programs, a diff --git a/docs/faq/Samba-meta-FAQ.sgml b/docs/faq/Samba-meta-FAQ.sgml index 2b54c6fa0f1..75038f19f53 100644 --- a/docs/faq/Samba-meta-FAQ.sgml +++ b/docs/faq/Samba-meta-FAQ.sgml @@ -3,15 +3,17 @@ v 0.1 23 Aug 1997 Dan Shearer Original Samba-meta-FAQ.sgml from Paul's sambafaq.sgml v 0.2 25 Aug 1997 Dan + v 0.3 7 Oct 1997 Paul + Changed samba.canberra refs to samba.anu.../samba/ --> <article> <title> Samba meta FAQ -<author>Dan Shearer & Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Dan Shearer & Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.1, 23 Aug '97 +<date>v 0.3, 7 Oct '97 <abstract> This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It @@ -286,7 +288,7 @@ See below for subscription information. discussion about Samba. <item>The WWW site 'SAMBA Web Pages' at <url -url="http://samba.canberra.edu.au/pub/samba/samba.html"> includes: +url="http://samba.anu.edu.au/samba/"> includes: <itemize> <item>Links to man pages and documentation, including this FAQ diff --git a/docs/faq/Samba-meta-FAQ.txt b/docs/faq/Samba-meta-FAQ.txt index 967dceac8de..65d9a57ff62 100644 --- a/docs/faq/Samba-meta-FAQ.txt +++ b/docs/faq/Samba-meta-FAQ.txt @@ -1,6 +1,6 @@ Samba meta FAQ - Dan Shearer & Paul Blackman, ictinus@lake.canberra.edu.au - v 0.1, 23 Aug '97 + Dan Shearer & Paul Blackman, ictinus@samba.anu.edu.au + v 0.3, 7 Oct '97 This is the meta-Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB and CIFS server product. It contains @@ -43,7 +43,7 @@ 2.11. Pizza supply details - 3. About CIFS and SMB + 3. About the CIFS and SMB Protocols 3.1. What is the Server Message Block (SMB) Protocol? @@ -53,7 +53,7 @@ 4. Designing A SMB and CIFS Network - 4.1. Workgroups, Browsing Domains and Authentication Domains + 4.1. Workgroups, Domains, Authentication and Browsing 4.1.1. Defining the Terms @@ -63,19 +63,16 @@ 4.2. Authentication Schemes - 4.2.1. Workgroup Mode Services - 4.2.2. Windows NT-Style Domain + 4.2.1. NIS - 4.2.3. NIS + 4.2.2. Kerberos - 4.2.4. Kerberos + 4.2.3. FTP - 4.2.5. FTP + 4.2.4. Default Server Method - 4.2.6. Default Server Method - - 4.2.7. Client-side Database Only + 4.2.5. Client-side Database Only 4.3. Post-Authentication: Netlogon, Logon Scripts, Profiles @@ -88,47 +85,87 @@ 11.. QQuuiicckk RReeffeerreennccee GGuuiiddeess ttoo SSaammbbaa DDooccuummeennttaattiioonn + We are endeavouring to provide links here to every major class of information about Samba or things related to Samba. We cannot list every document, but we are aiming for all documents to be at most two referrals from those listed here. This needs constant maintaining, so please send the author your feedback. + 11..11.. SSaammbbaa ffoorr tthhee IImmppaattiieenntt + You know you should read the documentation but can't wait to start? What you need to do then is follow the instructions in the following - documents, in order. This should be enough to get a _s_i_m_p_l_e site going - quickly. If you have any problems at all, refer back to this section - and do some more reading. - - 1. Getting Samba: ``Download Instructions'' - - 2. Installing Samba: making sure the binaries are in place and work. - At the moment there are two kinds of Samba server installs: Unix or - close relative <INSTALL.txt> and Others <Samba-Server- - FAQ.html#PortInfo>. Do not forget to - - 3. Debug sequence: If you think you have completed the previous step - and things aren't working properly work through the diagnosis - recipe. <DIAGNOSIS.txt> - - 4. Exporting files to SMB clients: You should read the manual pages - for smb.conf, but here is a quick answer guide. <Samba-Server- - FAQ.html#Exporting> - - 5. Controlling user access: the quickest and dirtiest way of sharing - resources is to use ``share level security.'' If you want to spend - more time and have a proper username and password database you must - read the paragraph on ``domain mode security.'' If you want - encryption (eg you are using Windows NT clients) follow the SMB - encryption instructions. <Samba-Server-FAQ.html#SMBEncryptionSteps> - 6. Browsing: if you are happy to type in "\samba-serverrename" at the - client end then do not read any further. Otherwise you need to - understand the ``browsing terminoligy'' and read <BROWSING.txt>. - - 7. Printing: See the printing quick answer guide. <Samba-Server- - FAQ.html#Printing> + documents in the order given. This should be enough to get a fairly + simple site going quickly. If you have any problems, refer back to + this meta-FAQ and follow the links to find more reading material. + + + + GGeettttiinngg SSaammbbaa:: + The fastest way to get Samba going is and install it is to have + an operating system for which the Samba team has put together an + installation package. To see if your OS is included have a look + at the directory /pub/samba/Binary_Packages/"OS_Vendor" on your + nearest mirror site <../MIRRORS>. If it is included follow the + installation instructions in the README file there and then do + some ``basic testing''. If you are not so fortunate, follow the + normal ``download instructions'' and then continue with + ``building and installing Samba''. + + + BBuuiillddiinngg aanndd IInnssttaalllliinngg SSaammbbaa:: + At the moment there are two kinds of Samba server installs + besides the prepackaged binaries mentioned in the previous step. + You need to decide if you have a Unix or close relative + <../UNIX_INSTALL.txt> or other supported operating system + <Samba-Server-FAQ.html#PortInfo>. + + + BBaassiicc TTeessttiinngg:: + Try to connect using the supplied smbclient command-line + program. You need to know the IP hostname of your server. A + service name must be defined in smb.conf, as given in the + examples (under many operating systems if there is a homes + service you can just use a valid username.) Then type smbclient + \hostnamevicename Under most Unixes you will need to put the + parameters within quotation marks. If this works, try connecting + from one of the SMB clients you were planning to use with Samba. + + + DDeebbuugg sseeqquueennccee:: + If you think you have completed the previous step and things + aren't working properly work through the diagnosis recipe. + <../DIAGNOSIS.txt> + + + EExxppoorrttiinngg ffiilleess ttoo SSMMBB cclliieennttss:: + You should read the manual pages for smb.conf, but here is a + quick answer guide. <Samba-Server-FAQ.html#Exporting> + + + CCoonnttrroolllliinngg uusseerr aacccceessss:: + the quickest and dirtiest way of sharing resources is to use + ``share level security.'' If you want to spend more time and + have a proper username and password database you must read the + paragraph on ``domain mode security.'' If you want encryption + (eg you are using Windows NT clients) follow the SMB encryption + instructions. <Samba-Server-FAQ.html#SMBEncryptionSteps> + + + BBrroowwssiinngg:: + if you are happy to type in "\samba-serverrename" at the client + end then do not read any further. Otherwise you need to + understand the ``browsing terminology'' and read <Samba-Server- + FAQ.html#NameBrowsing>. + + + PPrriinnttiinngg:: + See the printing quick answer guide. <Samba-Server- + FAQ.html#Printing> + If you have got everything working to this point, you can expect Samba to be stable and secure: these are its greatest strengths. However @@ -138,8 +175,11 @@ so on are all covered either in this document or in those it refers to. + 11..22.. AAllll SSaammbbaa DDooccuummeennttaattiioonn + + +o Meta-FAQ. This is the mother of all documents, and is the one you are reading now. The latest version is always at <http://samba.anu.edu.au/[.....]> but there is probably a much @@ -151,27 +191,31 @@ from...) +o <Samba-Client-FAQ.html> is the best starting point for information - about client-side issues, includes a list of all clients that work - with Samba. + about client-side issues, includes a list of all clients that are + known to work with Samba. - +o <samba-man-index.html> contains descriptions of and links to all - the Samba manual pages, in Unix man and postscript format. + +o manual pages <samba-man-index.html> contains descriptions of and + links to all the Samba manual pages, in Unix man and postscript + format. +o <samba-txt-index.html> has descriptions of and links to a large number of text files have been contributed to samba covering many - topics. These are gradually being absorbed into the FAQs and HOWTOS + topics. These are gradually being absorbed into the FAQs and HOWTOs but in the meantime you might find helpful answers here. +o + 22.. GGeenneerraall IInnffoorrmmaattiioonn + All about Samba - what it is, how to get it, related sources of - information, how to understand the version numbering scheme, pizza - details + information, how to understand the numbering scheme, pizza details. + 22..11.. WWhhaatt iiss SSaammbbaa?? + Samba is a suite of programs which work together to allow clients to access to a server's filespace and printers via the SMB (Server Message Block) and CIFS (Common Internet Filesystem) protocols. @@ -181,6 +225,7 @@ behave much like a LAN Server, Windows NT Server or Pathworks machine, only with added functionality and flexibility designed to make life easier for administrators. + This means that using Samba you can share a server's disks and printers to many sorts of network clients, including Lan Manager, Windows for Workgroups, Windows NT, Linux, OS/2, and AIX. There is @@ -188,6 +233,10 @@ which gives a user on the server an ftp-like interface to access filespace and printers on any other SMB/CIFS servers. + SMB has been implemented over many protocols, including XNS, NBT, IPX, + NetBEUI and TCP/IP. Samba only uses TCP/IP. This is not likely to + change although there have been some requests for NetBEUI support. + Many users report that compared to other SMB implementations Samba is more stable, faster, and compatible with more clients. Administrators of some large installations say that Samba is the only SMB server @@ -206,16 +255,19 @@ versions incorporate much effort by many net.helpers. The man pages and this FAQ were originally written by Karl Auer. + 22..22.. WWhhaatt iiss tthhee ccuurrrreenntt vveerrssiioonn ooff SSaammbbaa?? + At time of writing, the current version was 1.9.17. If you want to be sure check the bottom of the change-log file. <ftp://samba.anu.edu.au/pub/samba/alpha/change-log> - For more information see ``What do the version numbers mean?'' + 22..33.. WWhheerree ccaann II ggeett iitt?? + The Samba suite is available via anonymous ftp from samba.anu.edu.au and many mirror <../MIRRORS> sites. You will get much faster performance if you use a mirror site. The latest and greatest versions @@ -235,8 +287,18 @@ binaries for that platform. The VMS, OS/2, Netware and Amiga and other ports typically have binaries made available. + A special case is vendor-provided binary packages. Samba binaries and + default configuration files are put into packages for a specific + operating system. RedHat Linux and Sun Solaris (Sparc and x86) is + already included, and others such as OS/2 may follow. All packages are + in the directory: + + /pub/samba/Binary_Packages/"OS_Vendor" + + 22..44.. WWhhaatt ddoo tthhee vveerrssiioonn nnuummbbeerrss mmeeaann?? + It is not recommended that you run a version of Samba with the word "alpha" in its name unless you know what you are doing and are willing to do some debugging. Many, many people just get the latest @@ -248,6 +310,7 @@ How the scheme works: + 1. When major changes are made the version number is increased. For example, the transition from 1.9.16 to 1.9.17. However, this version number will not appear immediately and people should @@ -269,6 +332,7 @@ So the progression goes: + 1.9.16p10 (production) 1.9.16p11 (production) 1.9.17alpha1 (test sites only) @@ -277,24 +341,30 @@ 1.9.17 (production) 1.9.17p1 (production) + + The above system means that whenever someone looks at the samba ftp site they will be able to grab the highest numbered release without an alpha in the name and be sure of getting the current recommended version. + 22..55.. WWhheerree ccaann II ggoo ffoorr ffuurrtthheerr iinnffoorrmmaattiioonn?? + There are a number of places to look for more information on Samba, including: + +o Two mailing lists devoted to discussion of Samba-related matters. See below for subscription information. +o The newsgroup comp.protocols.smb, which has a great deal of discussion about Samba. - +o The WWW site 'SAMBA Web Pages' at - <http://samba.canberra.edu.au/pub/samba/samba.html> includes: + +o The WWW site 'SAMBA Web Pages' at <http://samba.anu.edu.au/samba/> + includes: + +o Links to man pages and documentation, including this FAQ @@ -306,14 +376,22 @@ +o This FAQ and the rest in its family + + 22..66.. HHooww ddoo II ssuubbssccrriibbee ttoo tthhee SSaammbbaa MMaaiilliinngg LLiissttss?? + Send email to listproc@samba.anu.edu.au. Make sure the subject line is blank, and include the following two lines in the body of the message: + + subscribe samba Firstname Lastname subscribe samba-announce Firstname Lastname + + + Obviously you should substitute YOUR first name for "Firstname" and YOUR last name for "Lastname"! Try not to send any signature, it sometimes confuses the list processor. @@ -327,20 +405,29 @@ listproc@samba.anu.edu.au. Make sure the subject line is blank, and include the following two lines in the body of the message: + + unsubscribe samba unsubscribe samba-announce + + + The FFrroomm:: line in your message _M_U_S_T be the same address you used when you subscribed. + 22..77.. SSoommeetthhiinngg''ss ggoonnee wwrroonngg -- wwhhaatt sshhoouulldd II ddoo?? + ## ****** IIMMPPOORRTTAANNTT!! ****** ## + DO NOT post messages on mailing lists or in newsgroups until you have carried out the first three steps given here! - 1. See if there are any likely looking entries in this FAQ! If you + + 1. See if there are any likely looking entries in this FAQ! If you have just installed Samba, have you run through the checklist in DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/DIAGNOSIS.txt>? It can save you a lot of time and effort. DIAGNOSIS.txt can also be @@ -370,8 +457,12 @@ succinct description of the symptom, the problem and the solution, so that an explanation can be incorporated into the next version. + + + 22..88.. HHooww ddoo II ssuubbmmiitt ppaattcchheess oorr bbuugg rreeppoorrttss?? + If you make changes to the source code, _p_l_e_a_s_e submit these patches so that everyone else gets the benefit of your work. This is one of the most important aspects to the maintainence of Samba. Send all patches @@ -412,6 +503,7 @@ Some extras : + +o what you did and what happened +o relevant parts of a debugging output file with debuglevel higher. @@ -420,8 +512,10 @@ +o anything else you think is useful to trace down the bug + 22..99.. WWhhaatt iiff II hhaavvee aann UURRGGEENNTT mmeessssaaggee ffoorr tthhee ddeevveellooppeerrss?? + If you have spotted something very serious and believe that it is important to contact the developers quickly send a message to samba- urgent@samba.anu.edu.au. This will be processed more quickly than mail @@ -434,21 +528,25 @@ 22..1100.. WWhhaatt iiff II nneeeedd ppaaiidd--ffoorr ssuuppppoorrtt?? + Samba has a large network of consultants who provide Samba support on a commercial basis. The list is included in the package in - Support.txt, and the latest version will always be on the main samba - ftp site. Any company in the world can request that the samba team - include their details in Support.txt so we can give no guarantee of - their services. + <../Support.txt>, and the latest version will always be on the main + samba ftp site. Any company in the world can request that the samba + team include their details in Support.txt so we can give no guarantee + of their services. + 22..1111.. PPiizzzzaa ssuuppppllyy ddeettaaiillss + Those who have registered in the Samba survey as "Pizza Factory" will already know this, but the rest may need some help. Andrew doesn't ask for payment, but he does appreciate it when people give him pizza. This calls for a little organisation when the pizza donor is twenty thousand kilometres away, but it has been done. + 1. Ring up your local branch of an international pizza chain and see if they honour their vouchers internationally. Pizza Hut do, which is how the entire Canberra Linux Users Group got to eat pizza one @@ -468,7 +566,10 @@ will probably get stuck in customs or torn apart by hungry sniffer dogs but it will have been a noble gesture. - 33.. AAbboouutt CCIIFFSS aanndd SSMMBB + + 33.. AAbboouutt tthhee CCIIFFSS aanndd SSMMBB PPrroottooccoollss + + 33..11.. WWhhaatt iiss tthhee SSeerrvveerr MMeessssaaggee BBlloocckk ((SSMMBB)) PPrroottooccooll?? @@ -493,6 +594,7 @@ implement more and more of these protocols. Samba began to take a significant share of the SMB server market. + 33..22.. WWhhaatt iiss tthhee CCoommmmoonn IInntteerrnneett FFiilleessyysstteemm ((CCIIFFSS))?? The initial pressure for Microsoft to document their current SMB @@ -516,6 +618,7 @@ The following is taken from <http://www.microsoft.com/intdev/cifs/> + CIFS defines a standard remote file system access protocol for use over the Internet, enabling groups of users to work together and share documents across the Internet or within their corporate @@ -526,6 +629,8 @@ users can open and share remote files on the Internet without having to install new software or change the way they work." + + If you consider CIFS as a backwardsly-compatible refinement of SMB that will work reasonably efficiently over the Internet you won't be too far wrong. @@ -537,6 +642,7 @@ reason why a site shouldn't conduct all its file and printer sharing with CIFS and yet have no Microsoft products at all. + 33..33.. WWhhaatt iiss BBrroowwssiinngg?? The term "Browsing" causes a lot of confusion. It is the part of the @@ -549,11 +655,16 @@ subject for debate. Look at the CIFS list archives to see what the experts think. + + + 44.. DDeessiiggnniinngg AA SSMMBB aanndd CCIIFFSS NNeettwwoorrkk + The big issues for installing any network of LAN or WAN file and print servers are + +o How and where usernames, passwords and other security information is stored @@ -562,6 +673,7 @@ +o What protocols the clients can converse with + If you buy Netware, Windows NT or just about any other LAN fileserver product you are expected to lock yourself into the product's preferred answers to these questions. This tendancy is restrictive and often @@ -573,65 +685,103 @@ administators, which means allowing as many combinations of clients, servers, operating systems and protocols as possible. - 44..11.. WWoorrkkggrroouuppss,, BBrroowwssiinngg DDoommaaiinnss aanndd AAuutthheennttiiccaattiioonn DDoommaaiinnss - The concepts of a Workgroup and a Domain are fundamental to SMB - networking. Although Microsoft integrates Workgroups and Domains - tightly with their authentication procedures there is no reason why - this has to be so in an SMB network. Groups of SMB machines can work - together just as well with Unix or OS/2 Samba servers as they can with - Windows NT servers, even though the password storage and access - methods are totally different. + 44..11.. WWoorrkkggrroouuppss,, DDoommaaiinnss,, AAuutthheennttiiccaattiioonn aanndd BBrroowwssiinngg + + + From the point of view of networking implementation, Domains and + Workgroups are _e_x_a_c_t_l_y the same, except for the client logon sequence. + Some kind of distributed authentication database is associated with a + domain (there are quite a few choices) and this adds so much + flexibility that many people think of a domain as a completely + different entity to a workgroup. From Samba's point of view a client + connecting to a service presents an authentication token, and it if it + is valid they have access. Samba does not care what mechanism was used + to generate that token in the first place. + + The SMB client logging on to a domain has an expectation that every + other server in the domain should accept the same authentication + information. However the network browsing functionality of domains + and workgroups is identical and is explained in <../BROWSING.txt>. + + There are some implementation differences: Windows 95 can be a member + of both a workgroup and a domain, but Windows NT cannot. Windows 95 + also has the concept of an "alternative workgroup". Samba can only be + a member of a single workgroup or domain, although this is due to + change with a future version when nmbd will be split into two daemons, + one for WINS and the other for browsing ( <../NetBIOS.txt> explains + what WINS is.) + 44..11..11.. DDeeffiinniinngg tthhee TTeerrmmss - A Workgroup (or Browsing Domain) is collection of machines that - maintain a common database contianing information about their shared - resources. They do not necessarily have any security information in - common. The database is dynamic, modified as servers come and go on - the network and as resources are added or deleted. The term "browsing" - refers to a user accessing the database via whatever interface the - client provides. SMB servers agree between themselves as to which ones - will maintain the browsing database. Workgroups can be anywhere on a - connected TCP/IP network, including on different subnets or anywhere - on the Interet. This is a very tricky part of SMB to implement. - Due to the convoluted history of SMB there is now conflicting - terminology describing Domains and Workgroups. "Domain" is used in the - browsing specifications to define that group of servers and clients - who share a common name and a common browsing database. The following - are used exclusively in the context of Workgroup browsing: - +o Domain Master Browser - +o Local Master Browser + WWoorrkkggrroouupp + means a collection of machines that maintain a common browsing + database containing information about their shared resources. + They do not necessarily have any security information in common + (if they do, it gets called a Domain.) The browsing database is + dynamic, modified as servers come and go on the network and as + resources are added or deleted. The term "browsing" refers to a + user accessing the database via whatever interface the client + provides, eg the OS/2 Workplace Shell or Windows 95 Explorer. + SMB servers agree between themselves as to which ones will + maintain the browsing database. Workgroups can be anywhere on a + connected TCP/IP network, including on different subnets or even + on the Interet. This is a very tricky part of SMB to implement. + - Alternative terms include confusing variations such as "Browse - Master", and "Master Browser" which we are trying to eliminate from - the Samba documentation. We are moving to the use of "Browsing Domain" - wherever the word "Domain" occurs in a workgroup context. Ideally - "Workgroup" would also be replaced by Browsing Domain but it is very - widely used terminology. + MMaasstteerr BBrroowwsseerrss + are machines which holds the master browsing database for a + workgroup or domain. There are two kinds of Master Browser: - Unfortunately the group of machines which use the the Microsoft method - of sharing authentication information (but not any of the many other - methods) is also called a Domain. As explained elsewhere Microsoft are - not making this protocol public and The following are used exclusively - in the context of Microsoft Authentication domains: - +o Primary Domain Controller + +o Domain Master Browser, which holds the master browsing + information for an entire domain, which may well cross multiple + TCP/IP subnets. - +o Backup Domain Controller + +o Local Master Browser, which holds the master browsing database + for a particular subnet and communicates with the Domain Master + Browser to get information on other subnets. + + Subnets are differentiated because browsing is based on + broadcasts, and broadcasts do not pass through routers. Subnets + are not routed: while it is possible to have more than one + subnet on a single network segment this is regarded as very bad + practice. + + Master Browsers (both Domain and Local) are elected dynamically + according to an algorithm which is supposed to take into account + the machine's ability to sustain the browsing load. Samba can be + configured to always act as a master browser, ie it always wins + elections under all circumstances, even against systems such as + a Windows NT Primary Domain Controller which themselves expect + to win. + + There are also Backup Browsers which are promoted to Master + Browsers in the event of a Master Browser disappearing from the + network. + + Alternative terms include confusing variations such as "Browse + Master", and "Master Browser" which we are trying to eliminate + from the Samba documentation. + + + DDoommaaiinn CCoonnttrroolllleerr + is a term which comes from the Microsoft and IBM etc + implementation of the LAN Manager protocols. It is tied to + authentication. There are other ways of doing domain + authentication, but the Windows NT method has a large market + share. The general issues are discussed in <../DOMAIN.txt> and + a Windows NT-specific discussion is in <../DOMAIN_CONTROL.txt>. - +o Domain Logon - These terms can be very confusing, and so in the Samba documentation - we are moving to the term "Authentication Domain" wherever Domain is - used in this sense. As a final touch of irony, all Authentication - Domains are also Browsing Domains. 44..11..22.. SShhaarreelleevveell ((WWoorrkkggrroouupp)) SSeeccuurriittyy SSeerrvviicceess + With the Samba setting "security = SHARE", all shared resources information about what password is associated with them but only hints as to what usernames might be valid (the hint can be 'all users', in @@ -643,16 +793,20 @@ authentication infrastructure present or requiring them to do more than fill in a dialogue box. + 44..11..33.. AAuutthheennttiiccaattiioonn DDoommaaiinn MMooddee SSeerrvviicceess + With the Samba settings "security = USER" or "security = SERVER" accesses to all resources are checked for username/password pair - matches in a more rigorous manner. This has the effect of emulating a - Microsoft Authentication Domain. Whether or not an Authentication - Domain is involved depends on how the network has been designed. + matches in a more rigorous manner. To the client, this has the effect + of emulating a Microsoft Domain. The client is not concerned whether + or not Samba looks up a Windows NT SAM or does it in some other way. + 44..22.. AAuutthheennttiiccaattiioonn SScchheemmeess + In the simple case authentication information is stored on a single server and the user types a password on connecting for the first time. However client operating systems often require a password before they @@ -661,7 +815,8 @@ different contexts just does not work. Some kind of distributed authentication database is needed. It must cope with password changes and provide for assigning groups of users the same level of access - permissions. + permissions. This is why Samba installations often choose to implement + a Domain model straight away. Authentication decisions are some of the biggest in designing a network. Are you going to use a scheme native to the client operating @@ -671,29 +826,49 @@ setups would be appreciated. refer to server FAQ for "passwd chat" passwd program password server etc etc... - 44..22..11.. WWoorrkkggrroouupp MMooddee SSeerrvviicceess - etc etc + 44..22..11.. NNIISS + + + For Windows 95, Windows for Workgroups and most other clients Samba + can be a domain controller and share the password database via NIS + transparently. Windows NT is different. Free NIS NT client + <http://www.dcs.qmw.ac.uk/~williams> + + + 44..22..22.. KKeerrbbeerrooss + + + Kerberos for US users only: Kerberos overview + <http://www.cygnus.com/product/unifying-security.html> Download + Kerberos <http://www.cygnus.com/product/kerbnet-download.html> + + + 44..22..33.. FFTTPP - 44..22..22.. WWiinnddoowwss NNTT--SSttyyllee DDoommaaiinn - Samba compiled with libdes - enabling encrypted passwords security = - server + Other NT w/s logon hack via NT - 44..22..33.. NNIISS - 44..22..44.. KKeerrbbeerrooss + 44..22..44.. DDeeffaauulltt SSeerrvveerr MMeetthhoodd - 44..22..55.. FFTTPP - 44..22..66.. DDeeffaauulltt SSeerrvveerr MMeetthhoodd - 44..22..77.. CClliieenntt--ssiiddee DDaattaabbaassee OOnnllyy + + + 44..22..55.. CClliieenntt--ssiiddee DDaattaabbaassee OOnnllyy + + 44..33.. PPoosstt--AAuutthheennttiiccaattiioonn:: NNeettllooggoonn,, LLooggoonn SSccrriippttss,, PPrrooffiilleess + + See <../DOMAIN.txt> + + 55.. CCrroossss--PPrroottooccooll FFiillee SShhaarriinngg + Samba is an important tool for... It is possible to... @@ -710,10 +885,40 @@ packages, Samba, and Linux (and other UNIX-based systems) see <http://www.eats.com/linux_mac_win.html> 3.5) Sniffing your nework + + 66.. MMiisscceellllaanneeoouuss + 66..11.. IIss SSaammbbaa YYeeaarr 22000000 ccoommpplliiaanntt?? + The CIFS protocol that Samba implements negotiates times in various formats, all of which are able to cope with dates beyond 2000. + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/faq/sambafaq-1.html b/docs/faq/sambafaq-1.html index 4b9e589e843..c010e50e011 100644 --- a/docs/faq/sambafaq-1.html +++ b/docs/faq/sambafaq-1.html @@ -197,7 +197,7 @@ There are a number of places to look for more information on Samba, including: <LI>Two mailing lists devoted to discussion of Samba-related matters. </LI> <LI>The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. </LI> <LI>The WWW site 'SAMBA Web Pages' at -<A HREF="http://samba.canberra.edu.au/pub/samba/samba.html">http://samba.canberra.edu.au/pub/samba/samba.html</A> includes: +<A HREF="http://samba.edu.au/samba/">http://samba.edu.au/samba/</A> includes: <UL> <LI>Links to man pages and documentation, including this FAQ</LI> <LI>A comprehensive survey of Samba users.</LI> diff --git a/docs/faq/sambafaq-3.html b/docs/faq/sambafaq-3.html index 8b24de54f23..1b5dcf4d9aa 100644 --- a/docs/faq/sambafaq-3.html +++ b/docs/faq/sambafaq-3.html @@ -76,7 +76,7 @@ To syncronize your PC's clock with your Samba server: <UL> <LI> Copy timesync.pif to your windows directory</LI> <LI> timesync.pif can be found at: -<A HREF="http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif">http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif</A></LI> +<A HREF="http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif">http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif</A></LI> <LI> Add timesync.pif to your 'Start Up' group/folder</LI> <LI> Open the properties dialog box for the program/icon</LI> <LI> Make sure the 'Run Minimized' option is set in program 'Properties'</LI> diff --git a/docs/faq/sambafaq.html b/docs/faq/sambafaq.html index 9e3d21ad137..9c45d524dd3 100644 --- a/docs/faq/sambafaq.html +++ b/docs/faq/sambafaq.html @@ -45,7 +45,7 @@ Table of Contents <HR> <H1> Samba FAQ</H1> -<H2>Paul Blackman, <CODE>ictinus@lake.canberra.edu.au</CODE></H2>v 0.7, June '97 +<H2>Paul Blackman, <CODE>ictinus@samba.anu.edu.au</CODE></H2>v 0.8, June '97 <P><HR><EM> This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server allows file and printer connections from clients such as Windows, diff --git a/docs/faq/sambafaq.sgml b/docs/faq/sambafaq.sgml index 951ad822edb..d306881b56b 100644 --- a/docs/faq/sambafaq.sgml +++ b/docs/faq/sambafaq.sgml @@ -9,15 +9,17 @@ 9 June 1997 Paul Lots of changes, added doco list, updated compatible systems list added NT SP3 entry, added Year 2000 entry, Getting ready for 1.9.17 + v 0.8 7th Oct 97 Paul + changed samba.canberra entries to samba.anu.../samba/ --> <article> <title> Samba FAQ -<author>Paul Blackman, <tt>ictinus@lake.canberra.edu.au</tt> +<author>Paul Blackman, <tt>ictinus@samba.anu.edu.au</tt> -<date>v 0.7, June '97 +<date>v 0.8, June '97 <abstract> This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server @@ -191,7 +193,7 @@ There are a number of places to look for more information on Samba, including: <itemize> <item>Two mailing lists devoted to discussion of Samba-related matters. <item>The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. -<item>The WWW site 'SAMBA Web Pages' at <url url="http://samba.canberra.edu.au/pub/samba/samba.html"> includes: +<item>The WWW site 'SAMBA Web Pages' at <url url="http://samba.edu.au/samba/"> includes: <itemize> <item>Links to man pages and documentation, including this FAQ <item>A comprehensive survey of Samba users. @@ -562,7 +564,8 @@ To syncronize your PC's clock with your Samba server: <itemize> <item> Copy timesync.pif to your windows directory <item> timesync.pif can be found at: - <url url="http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif"> + <url +url="http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif"> <item> Add timesync.pif to your 'Start Up' group/folder <item> Open the properties dialog box for the program/icon <item> Make sure the 'Run Minimized' option is set in program 'Properties' diff --git a/docs/faq/sambafaq.txt b/docs/faq/sambafaq.txt index e7f5f32a20d..7108846ae67 100644 --- a/docs/faq/sambafaq.txt +++ b/docs/faq/sambafaq.txt @@ -1,6 +1,6 @@ Samba FAQ - Paul Blackman, ictinus@lake.canberra.edu.au - v 0.7, June '97 + Paul Blackman, ictinus@samba.anu.edu.au + v 0.8, June '97 This is the Frequently Asked Questions (FAQ) document for Samba, the free and very popular SMB server product. An SMB server allows file @@ -92,7 +92,7 @@ 5.1. Is Samba Year 2000 compliant? ______________________________________________________________________ - 1. General Information + 11.. GGeenneerraall IInnffoorrmmaattiioonn @@ -101,7 +101,7 @@ details - 1.1. What is Samba? + 11..11.. WWhhaatt iiss SSaammbbaa?? Samba is a suite of programs which work together to allow clients to @@ -122,30 +122,30 @@ The components of the suite are (in summary): - o smbd, the SMB server. This handles actual connections from clients, + +o ssmmbbdd, the SMB server. This handles actual connections from clients, doing all the file, permission and username work - o nmbd, the Netbios name server, which helps clients locate servers, + +o nnmmbbdd, the Netbios name server, which helps clients locate servers, doing the browsing work and managing domains as this capability is being built into Samba - o smbclient, the Unix-hosted client program + +o ssmmbbcclliieenntt, the Unix-hosted client program - o smbrun, a little 'glue' program to help the server run external + +o ssmmbbrruunn, a little 'glue' program to help the server run external programs - o testprns, a program to test server access to printers + +o tteessttpprrnnss, a program to test server access to printers - o testparms, a program to test the Samba configuration file for + +o tteessttppaarrmmss, a program to test the Samba configuration file for correctness - o smb.conf, the Samba configuration file + +o ssmmbb..ccoonnff, the Samba configuration file - o smbprint, a sample script to allow a Unix host to use smbclient to + +o ssmmbbpprriinntt, a sample script to allow a Unix host to use smbclient to print to an SMB server - o Documentation! DON'T neglect to read it - you will save a great + +o DDooccuummeennttaattiioonn!! DON'T neglect to read it - you will save a great deal of time! The suite is supplied with full source (of course!) and is GPLed. @@ -155,7 +155,7 @@ and this FAQ were originally written by Karl Auer. - 1.2. What is the current version of Samba? + 11..22.. WWhhaatt iiss tthhee ccuurrrreenntt vveerrssiioonn ooff SSaammbbaa?? At time of writing, the current version was 1.9.17. If you want to be @@ -165,7 +165,7 @@ For more information see ``What do the version numbers mean?'' - 1.3. Where can I get it? + 11..33.. WWhheerree ccaann II ggeett iitt?? The Samba suite is available via anonymous ftp from samba.anu.edu.au. @@ -185,7 +185,7 @@ do contain Samba binaries for that platform. - 1.4. What do the version numbers mean? + 11..44.. WWhhaatt ddoo tthhee vveerrssiioonn nnuummbbeerrss mmeeaann?? It is not recommended that you run a version of Samba with the word @@ -234,7 +234,7 @@ sion. - 1.5. What platforms are supported? + 11..55.. WWhhaatt ppllaattffoorrmmss aarree ssuuppppoorrtteedd?? Many different platforms have run Samba successfully. The platforms @@ -242,188 +242,188 @@ At time of writing, the Makefile claimed support for: - o A/UX 3.0 + +o A/UX 3.0 - o AIX + +o AIX - o Altos Series 386/1000 + +o Altos Series 386/1000 - o Amiga + +o Amiga - o Apollo Domain/OS sr10.3 + +o Apollo Domain/OS sr10.3 - o BSDI + +o BSDI - o B.O.S. (Bull Operating System) + +o B.O.S. (Bull Operating System) - o Cray, Unicos 8.0 + +o Cray, Unicos 8.0 - o Convex + +o Convex - o DGUX. + +o DGUX. - o DNIX. + +o DNIX. - o FreeBSD + +o FreeBSD - o HP-UX + +o HP-UX - o Intergraph. + +o Intergraph. - o Linux with/without shadow passwords and quota + +o Linux with/without shadow passwords and quota - o LYNX 2.3.0 + +o LYNX 2.3.0 - o MachTen (a unix like system for Macintoshes) + +o MachTen (a unix like system for Macintoshes) - o Motorola 88xxx/9xx range of machines + +o Motorola 88xxx/9xx range of machines - o NetBSD + +o NetBSD - o NEXTSTEP Release 2.X, 3.0 and greater (including OPENSTEP for + +o NEXTSTEP Release 2.X, 3.0 and greater (including OPENSTEP for Mach). - o OS/2 using EMX 0.9b + +o OS/2 using EMX 0.9b - o OSF1 + +o OSF1 - o QNX 4.22 + +o QNX 4.22 - o RiscIX. + +o RiscIX. - o RISCOs 5.0B + +o RISCOs 5.0B - o SEQUENT. + +o SEQUENT. - o SCO (including: 3.2v2, European dist., OpenServer 5) + +o SCO (including: 3.2v2, European dist., OpenServer 5) - o SGI. + +o SGI. - o SMP_DC.OSx v1.1-94c079 on Pyramid S series + +o SMP_DC.OSx v1.1-94c079 on Pyramid S series - o SONY NEWS, NEWS-OS (4.2.x and 6.1.x) + +o SONY NEWS, NEWS-OS (4.2.x and 6.1.x) - o SUNOS 4 + +o SUNOS 4 - o SUNOS 5.2, 5.3, and 5.4 (Solaris 2.2, 2.3, and '2.4 and later') + +o SUNOS 5.2, 5.3, and 5.4 (Solaris 2.2, 2.3, and '2.4 and later') - o Sunsoft ISC SVR3V4 + +o Sunsoft ISC SVR3V4 - o SVR4 + +o SVR4 - o System V with some berkely extensions (Motorola 88k R32V3.2). + +o System V with some berkely extensions (Motorola 88k R32V3.2). - o ULTRIX. + +o ULTRIX. - o UNIXWARE + +o UNIXWARE - o UXP/DS + +o UXP/DS - 1.6. How can I find out more about Samba? + 11..66.. HHooww ccaann II ffiinndd oouutt mmoorree aabboouutt SSaammbbaa?? There are a number of places to look for more information on Samba, including: - o Two mailing lists devoted to discussion of Samba-related matters. + +o Two mailing lists devoted to discussion of Samba-related matters. - o The newsgroup, comp.protocols.smb, which has a great deal of + +o The newsgroup, comp.protocols.smb, which has a great deal of discussion on Samba. - o The WWW site 'SAMBA Web Pages' at - <http://samba.canberra.edu.au/pub/samba/samba.html> includes: + +o The WWW site 'SAMBA Web Pages' at <http://samba.edu.au/samba/> + includes: - o Links to man pages and documentation, including this FAQ + +o Links to man pages and documentation, including this FAQ - o A comprehensive survey of Samba users. + +o A comprehensive survey of Samba users. - o A searchable hypertext archive of the Samba mailing list. + +o A searchable hypertext archive of the Samba mailing list. - o Links to Samba source code, binaries, and mirrors of both. + +o Links to Samba source code, binaries, and mirrors of both. - o The long list of topic documentation. These files can be found in + +o The long list of topic documentation. These files can be found in the 'docs' directory of the Samba source, or at <ftp://samba.anu.edu.au/pub/samba/docs/> - o Application_Serving.txt + +o Application_Serving.txt <ftp://samba.anu.edu.au/pub/samba/docs/Application_Serving.txt> - o BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt> + +o BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/docs/BROWSING.txt> - o BUGS.txt <ftp://samba.anu.edu.au/pub/samba/docs/BUGS.txt> + +o BUGS.txt <ftp://samba.anu.edu.au/pub/samba/docs/BUGS.txt> - o DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/docs/DIAGNOSIS.txt> + +o DIAGNOSIS.txt <ftp://samba.anu.edu.au/pub/samba/docs/DIAGNOSIS.txt> - o DNIX.txt <ftp://samba.anu.edu.au/pub/samba/docs/DNIX.txt> + +o DNIX.txt <ftp://samba.anu.edu.au/pub/samba/docs/DNIX.txt> - o DOMAIN.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN.txt> + +o DOMAIN.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN.txt> - o CONTROL.txt + +o CONTROL.txt <ftp://samba.anu.edu.au/pub/samba/docs/DOMAIN_CONTROL.txt> - o ENCRYPTION.txt + +o ENCRYPTION.txt <ftp://samba.anu.edu.au/pub/samba/docs/ENCRYPTION.txt> - o Faxing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Faxing.txt> + +o Faxing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Faxing.txt> - o GOTCHAS.txt <ftp://samba.anu.edu.au/pub/samba/docs/GOTCHAS.txt> + +o GOTCHAS.txt <ftp://samba.anu.edu.au/pub/samba/docs/GOTCHAS.txt> - o HINTS.txt <ftp://samba.anu.edu.au/pub/samba/docs/HINTS.txt> + +o HINTS.txt <ftp://samba.anu.edu.au/pub/samba/docs/HINTS.txt> - o INSTALL.sambatar + +o INSTALL.sambatar <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.sambatar> - o INSTALL.txt <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.txt> + +o INSTALL.txt <ftp://samba.anu.edu.au/pub/samba/docs/INSTALL.txt> - o MIRRORS <ftp://samba.anu.edu.au/pub/samba/docs/MIRRORS> + +o MIRRORS <ftp://samba.anu.edu.au/pub/samba/docs/MIRRORS> - o NetBIOS.txt <ftp://samba.anu.edu.au/pub/samba/docs/NetBIOS.txt> + +o NetBIOS.txt <ftp://samba.anu.edu.au/pub/samba/docs/NetBIOS.txt> - o OS2.txt <ftp://samba.anu.edu.au/pub/samba/docs/OS2.txt> + +o OS2.txt <ftp://samba.anu.edu.au/pub/samba/docs/OS2.txt> - o PROJECTS <ftp://samba.anu.edu.au/pub/samba/docs/PROJECTS> + +o PROJECTS <ftp://samba.anu.edu.au/pub/samba/docs/PROJECTS> - o Passwords.txt <ftp://samba.anu.edu.au/pub/samba/docs/Passwords.txt> + +o Passwords.txt <ftp://samba.anu.edu.au/pub/samba/docs/Passwords.txt> - o Printing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Printing.txt> + +o Printing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Printing.txt> - o README.DCEDFS <ftp://samba.anu.edu.au/pub/samba/docs/README.DCEDFS> + +o README.DCEDFS <ftp://samba.anu.edu.au/pub/samba/docs/README.DCEDFS> - o README.OS2 <ftp://samba.anu.edu.au/pub/samba/docs/README.OS2> + +o README.OS2 <ftp://samba.anu.edu.au/pub/samba/docs/README.OS2> - o README.jis <ftp://samba.anu.edu.au/pub/samba/docs/README.jis> + +o README.jis <ftp://samba.anu.edu.au/pub/samba/docs/README.jis> - o README.sambatar + +o README.sambatar <ftp://samba.anu.edu.au/pub/samba/docs/README.sambatar> - o SCO.txt <ftp://samba.anu.edu.au/pub/samba/docs/SCO.txt> + +o SCO.txt <ftp://samba.anu.edu.au/pub/samba/docs/SCO.txt> - o SMBTAR.notes <ftp://samba.anu.edu.au/pub/samba/docs/SMBTAR.notes> + +o SMBTAR.notes <ftp://samba.anu.edu.au/pub/samba/docs/SMBTAR.notes> - o Speed.txt <ftp://samba.anu.edu.au/pub/samba/docs/Speed.txt> + +o Speed.txt <ftp://samba.anu.edu.au/pub/samba/docs/Speed.txt> - o Support.txt <ftp://samba.anu.edu.au/pub/samba/docs/Support.txt> + +o Support.txt <ftp://samba.anu.edu.au/pub/samba/docs/Support.txt> - o THANKS <ftp://samba.anu.edu.au/pub/samba/docs/THANKS> + +o THANKS <ftp://samba.anu.edu.au/pub/samba/docs/THANKS> - o Tracing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Tracing.txt> + +o Tracing.txt <ftp://samba.anu.edu.au/pub/samba/docs/Tracing.txt> - o SMB.txt <ftp://samba.anu.edu.au/pub/samba/docs/UNIX-SMB.txt> + +o SMB.txt <ftp://samba.anu.edu.au/pub/samba/docs/UNIX-SMB.txt> - o Warp.txt <ftp://samba.anu.edu.au/pub/samba/docs/Warp.txt> + +o Warp.txt <ftp://samba.anu.edu.au/pub/samba/docs/Warp.txt> - o WinNT.txt <ftp://samba.anu.edu.au/pub/samba/docs/WinNT.txt> + +o WinNT.txt <ftp://samba.anu.edu.au/pub/samba/docs/WinNT.txt> - o history <ftp://samba.anu.edu.au/pub/samba/docs/history> + +o history <ftp://samba.anu.edu.au/pub/samba/docs/history> - o level.txt + +o level.txt <ftp://samba.anu.edu.au/pub/samba/docs/security_level.txt> - o slip.htm <ftp://samba.anu.edu.au/pub/samba/docs/wfw_slip.htm> + +o slip.htm <ftp://samba.anu.edu.au/pub/samba/docs/wfw_slip.htm> - 1.7. How do I subscribe to the Samba Mailing Lists? + 11..77.. HHooww ddoo II ssuubbssccrriibbee ttoo tthhee SSaammbbaa MMaaiilliinngg LLiissttss?? Send email to listproc@samba.anu.edu.au. Make sure the subject line is @@ -456,14 +456,14 @@ - The From: line in your message MUST be the same address you used when + The FFrroomm:: line in your message _M_U_S_T be the same address you used when you subscribed. - 1.8. Something's gone wrong - what should I do? + 11..88.. SSoommeetthhiinngg''ss ggoonnee wwrroonngg -- wwhhaatt sshhoouulldd II ddoo?? - # *** IMPORTANT! *** # + ## ****** IIMMPPOORRTTAANNTT!! ****** ## DO NOT post messages on mailing lists or in newsgroups until you have carried out the first three steps given here! @@ -501,7 +501,7 @@ Tridgell or any other individual, they may be lost if you do. - 1.9. Pizza supply details + 11..99.. PPiizzzzaa ssuuppppllyy ddeettaaiillss Those who have registered in the Samba survey as "Pizza Factory" will @@ -531,11 +531,11 @@ hungry sniffer dogs but it will have been a noble gesture. - 2. Compiling and installing Samba on a Unix host + 22.. CCoommppiilliinngg aanndd iinnssttaalllliinngg SSaammbbaa oonn aa UUnniixx hhoosstt - 2.1. I can't see the Samba server in any browse lists! + 22..11.. II ccaann''tt sseeee tthhee SSaammbbaa sseerrvveerr iinn aannyy bbrroowwssee lliissttss!! See BROWSING.txt <ftp://samba.anu.edu.au/pub/samba/BROWSING.txt> for @@ -557,14 +557,14 @@ client to client - check your client's documentation. - 2.2. Some files that I KNOW are on the server doesn't show up when I - view the files from my client! + 22..22.. SSoommee ffiilleess tthhaatt II KKNNOOWW aarree oonn tthhee sseerrvveerr ddooeessnn''tt sshhooww uupp wwhheenn II + vviieeww tthhee ffiilleess ffrroomm mmyy cclliieenntt!! See the next question. - 2.3. Some files on the server show up with really wierd filenames - when I view the files from my client! + 22..33.. SSoommee ffiilleess oonn tthhee sseerrvveerr sshhooww uupp wwiitthh rreeaallllyy wwiieerrdd ffiilleennaammeess + wwhheenn II vviieeww tthhee ffiilleess ffrroomm mmyy cclliieenntt!! If you check what files are not showing up, you will note that they @@ -579,7 +579,7 @@ "mangled names = yes". - 2.4. My client reports "cannot locate specified computer" or similar + 22..44.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott llooccaattee ssppeecciiffiieedd ccoommppuutteerr"" oorr ssiimmiillaarr This indicates one of three things: You supplied an incorrect server @@ -610,8 +610,8 @@ tests :-) - 2.5. My client reports "cannot locate specified share name" or simi- - lar + 22..55.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott llooccaattee ssppeecciiffiieedd sshhaarree nnaammee"" oorr ssiimmii-- + llaarr This message indicates that your client CAN locate the specified @@ -624,19 +624,19 @@ to specify a service name correctly), read on: - o Many clients cannot accept or use service names longer than eight + +o Many clients cannot accept or use service names longer than eight characters. - o Many clients cannot accept or use service names containing spaces. + +o Many clients cannot accept or use service names containing spaces. - o Some servers (not Samba though) are case sensitive with service + +o Some servers (not Samba though) are case sensitive with service names. - o Some clients force service names into upper case. + +o Some clients force service names into upper case. - 2.6. My client reports "cannot find domain controller", "cannot log - on to the network" or similar + 22..66.. MMyy cclliieenntt rreeppoorrttss ""ccaannnnoott ffiinndd ddoommaaiinn ccoonnttrroolllleerr"",, ""ccaannnnoott lloogg + oonn ttoo tthhee nneettwwoorrkk"" oorr ssiimmiillaarr Nothing is wrong - Samba does not implement the primary domain name @@ -658,7 +658,7 @@ - 2.7. Printing doesn't work :-( + 22..77.. PPrriinnttiinngg ddooeessnn''tt wwoorrkk ::--(( Make sure that the specified print command for the service you are @@ -689,8 +689,8 @@ mechanism. - 2.8. My programs install on the server OK, but refuse to work prop- - erly + 22..88.. MMyy pprrooggrraammss iinnssttaallll oonn tthhee sseerrvveerr OOKK,, bbuutt rreeffuussee ttoo wwoorrkk pprroopp-- + eerrllyy There are numerous possible reasons for this, but one MAJOR @@ -706,7 +706,7 @@ Tridgell know via email at samba-bugs@samba.anu.edu.au. - 2.9. My "server string" doesn't seem to be recognised + 22..99.. MMyy ""sseerrvveerr ssttrriinngg"" ddooeessnn''tt sseeeemm ttoo bbee rreeccooggnniisseedd OR My client reports the default setting, eg. "Samba 1.9.15p4", @@ -719,8 +719,8 @@ the "server string" field of smb.conf, -C for nmbd is now obsolete. - 2.10. My client reports "This server is not configured to list shared - resources" + 22..1100.. MMyy cclliieenntt rreeppoorrttss ""TThhiiss sseerrvveerr iiss nnoott ccoonnffiigguurreedd ttoo lliisstt sshhaarreedd + rreessoouurrcceess"" Your guest account is probably invalid for some reason. Samba uses the @@ -730,7 +730,7 @@ See also 'guest account' in smb.conf man page. - 2.11. Log message "you appear to have a trapdoor uid system" + 22..1111.. LLoogg mmeessssaaggee ""yyoouu aappppeeaarr ttoo hhaavvee aa ttrraappddoooorr uuiidd ssyysstteemm"" This can have several causes. It might be because you are using a uid @@ -765,12 +765,12 @@ as uid 65535 will actually run as root. This is not good! - 3. Common client questions + 33.. CCoommmmoonn cclliieenntt qquueessttiioonnss - 3.1. Are there any Macintosh clients for Samba? + 33..11.. AArree tthheerree aannyy MMaacciinnttoosshh cclliieennttss ffoorr SSaammbbaa?? Yes! Thursby now have a CIFS Client / Server called DAVE - see @@ -790,7 +790,7 @@ Windows users, these packages offer to Macs. For more info on these packages, Samba, and Linux (and other UNIX-based systems) see <http://www.eats.com/linux_mac_win.html> - 3.2. Session request failed (131,130)" error + 33..22.. SSeessssiioonn rreeqquueesstt ffaaiilleedd ((113311,,113300))"" eerrrroorr The following answer is provided by John E. Miller: @@ -819,26 +819,26 @@ you'd have to use smbclient -iSomeStr otherparms in connecting to it. - 3.3. How do I synchronise my PC's clock with my Samba server? + 33..33.. HHooww ddoo II ssyynncchhrroonniissee mmyy PPCC''ss cclloocckk wwiitthh mmyy SSaammbbaa sseerrvveerr?? To syncronize your PC's clock with your Samba server: - o Copy timesync.pif to your windows directory + +o Copy timesync.pif to your windows directory - o timesync.pif can be found at: - <http://samba.canberra.edu.au/pub/samba/binaries/miscellaneous/timesync.pif> + +o timesync.pif can be found at: + <http://samba.anu.edu.au/samba/binaries/miscellaneous/timesync.pif> - o Add timesync.pif to your 'Start Up' group/folder + +o Add timesync.pif to your 'Start Up' group/folder - o Open the properties dialog box for the program/icon + +o Open the properties dialog box for the program/icon - o Make sure the 'Run Minimized' option is set in program 'Properties' + +o Make sure the 'Run Minimized' option is set in program 'Properties' - o Change the command line section that reads \sambahost to reflect + +o Change the command line section that reads \sambahost to reflect the name of your server. - o Close the properties dialog box by choosing 'OK' + +o Close the properties dialog box by choosing 'OK' Each time you start your computer (or login for Win95) your PC will synchronize its clock with your Samba server. @@ -858,7 +858,7 @@ as one of the lines in the logon script. - 3.4. Problems with WinDD, NTrigue, WinCenterPro etc + 33..44.. PPrroobblleemmss wwiitthh WWiinnDDDD,, NNTTrriigguuee,, WWiinnCCeenntteerrPPrroo eettcc All of the above programs are applications that sit on an NT box and @@ -900,7 +900,7 @@ home directory. Use \serversername instead. - 3.5. Problem with printers under NT + 33..55.. PPrroobblleemm wwiitthh pprriinntteerrss uunnddeerr NNTT This info from Stefan Hergeth hergeth@f7axp1.informatik.fh-muenchen.de @@ -929,7 +929,7 @@ try it yet. - 3.6. Why are my file's timestamps off by an hour, or by a few hours? + 33..66.. WWhhyy aarree mmyy ffiillee''ss ttiimmeessttaammppss ooffff bbyy aann hhoouurr,, oorr bbyy aa ffeeww hhoouurrss?? This is from Paul Eggert eggert@twinsun.com. @@ -973,20 +973,20 @@ where: - o `Std' is the standard time designation (e.g. `PST'). + +o `Std' is the standard time designation (e.g. `PST'). - o `Offset' is the number of hours behind UTC (e.g. `8'). Prepend + +o `Offset' is the number of hours behind UTC (e.g. `8'). Prepend a `-' if you are ahead of UTC, and append `:30' if you are at a half-hour offset. Omit all the remaining items if you do not use daylight-saving time. - o `Dst' is the daylight-saving time designation (e.g. `PDT'). + +o `Dst' is the daylight-saving time designation (e.g. `PDT'). The optional second `Offset' is the number of hours that daylight-saving time is behind UTC. The default is 1 hour ahead of standard time. - o `Date/Time,Date/Time' specify when daylight-saving time starts + +o `Date/Time,Date/Time' specify when daylight-saving time starts and ends. The format for a date is `Mm.n.d', which specifies the dth day (0 is Sunday) of the nth week of the mth month, where week 5 means the last such day in the month. The format @@ -1005,7 +1005,7 @@ Samba server to 1.9.16alpha10 or later. - 3.7. How do I set the printer driver name correctly? + 33..77.. HHooww ddoo II sseett tthhee pprriinntteerr ddrriivveerr nnaammee ccoorrrreeccttllyy?? Question: On NT, I opened "Printer Manager" and "Connect to Printer". @@ -1050,17 +1050,17 @@ this is effectively what older versions of Samba did, so if that worked for you then give it a go. If this does work then let us know - via samba-bugs@samba.anu.edu.au, and we'll make it the default. Currently - the default is a 0 length string. + via samba-bugs@samba.anu.edu.au, and we'll make it the default. Cur- + rently the default is a 0 length string. - 3.8. I've applied NT 4.0 SP3, and now I can't access Samba shares, - Why? + 33..88.. II''vvee aapppplliieedd NNTT 44..00 SSPP33,, aanndd nnooww II ccaann''tt aacccceessss SSaammbbaa sshhaarreess,, + WWhhyy?? As of SP3, Microsoft has decided that they will no longer default to passing clear text passwords over the network. To enable access to - Samba shares from NT 4.0 SP3, you must do ONE of two things: + Samba shares from NT 4.0 SP3, you must do OONNEE of two things: 1. Set the Samba configuration option 'security = user' and implement all of the stuff detailed in ENCRYPTION.txt @@ -1071,13 +1071,13 @@ <http://www.microsoft.com/kb/articles/q166/7/30.htm> - 4. Specific client application problems + 44.. SSppeecciiffiicc cclliieenntt aapppplliiccaattiioonn pprroobblleemmss - 4.1. MS Office Setup reports "Cannot change properties of 'MSOF- - FICEUP.INI'" + 44..11.. MMSS OOffffiiccee SSeettuupp rreeppoorrttss ""CCaannnnoott cchhaannggee pprrooppeerrttiieess ooff ''MMSSOOFF-- + FFIICCEEUUPP..IINNII''"" When installing MS Office on a Samba drive for which you have admin @@ -1093,11 +1093,11 @@ to fix the owner. - 5. Miscellaneous + 55.. MMiisscceellllaanneeoouuss - 5.1. Is Samba Year 2000 compliant? + 55..11.. IIss SSaammbbaa YYeeaarr 22000000 ccoommpplliiaanntt?? The CIFS protocol that Samba implements negotiates times in various -- cgit From e923585ef0f6b6845b1d8042f8c461411e846e1a Mon Sep 17 00:00:00 2001 From: Paul Blackman <ictinus@samba.org> Date: Tue, 21 Oct 1997 12:38:07 +0000 Subject: Removed references to samba.canberra, replacing with samba.anu Added mirror sites. --- README | 6 +++--- docs/announce | 2 +- docs/manpages/samba.7 | 2 +- docs/textdocs/BUGS.txt | 2 +- docs/textdocs/MIRRORS.txt | 49 +++++++++++++++++++++--------------------- docs/textdocs/UNIX_INSTALL.txt | 2 +- 6 files changed, 32 insertions(+), 31 deletions(-) diff --git a/README b/README index 15dd87e87e4..10d9d931e55 100644 --- a/README +++ b/README @@ -47,7 +47,7 @@ printers) from unix, Netware and other operating systems - a tar extension to the client for backing up PCs For a much better overview have a look at the web site at -http://samba.canberra.edu.au/pub/samba, and browse the user survey. +http://samba.anu.edu.au/samba, and browse the user survey. Related packages include: @@ -140,14 +140,14 @@ WEB SITE A Samba WWW site has been setup with lots of useful info. Connect to: -http://samba.canberra.edu.au/pub/samba/ +http://samba.anu.edu.au/samba/ As well as general information and documentation, this also has searchable archives of the mailing list and a user survey that shows who else is using this package. Have you registered with the survey yet? :-) It is maintained by Paul Blackman (thanks Paul!). You can contact him -at ictinus@lake.canberra.edu.au. +at ictinus@samba.anu.edu.au. diff --git a/docs/announce b/docs/announce index adcde8966f8..a03ddcd0e6a 100644 --- a/docs/announce +++ b/docs/announce @@ -127,7 +127,7 @@ There is also often quite a bit of discussion about Samba on the newsgroup comp.protocols.smb. A WWW site with lots of Samba info can be found at -http://samba.canberra.edu.au/pub/samba/ +http://samba.anu.edu.au/samba/ The Samba Team (Contact: samba-bugs@samba.anu.edu.au) June 1996 diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7 index 7e98c850d41..7260cbad396 100644 --- a/docs/manpages/samba.7 +++ b/docs/manpages/samba.7 @@ -65,7 +65,7 @@ the mailing list are given in the README file that comes with Samba. If you have access to a WWW viewer (such as Netscape or Mosaic) then you will also find lots of useful information, including back issues -of the Samba mailing list, at http://samba.canberra.edu.au/pub/samba/ +of the Samba mailing list, at http://samba.anu.edu.au/samba/ .SH AUTHOR The main author of the Samba suite is Andrew Tridgell. He may be diff --git a/docs/textdocs/BUGS.txt b/docs/textdocs/BUGS.txt index 0bd12e8af0a..5fc069371b3 100644 --- a/docs/textdocs/BUGS.txt +++ b/docs/textdocs/BUGS.txt @@ -25,7 +25,7 @@ that list that may be able to help you. You may also like to look though the recent mailing list archives, which are conveniently accessible on the Samba web pages -at http://samba.canberra.edu.au/pub/samba/ +at http://samba.anu.edu.au/samba/ GENERAL INFO diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index 01bc277a20b..2ce18b6d5b0 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -1,23 +1,34 @@ The main Samba ftp site is samba.anu.edu.au in pub/samba/. Contact samba-bugs@samba.anu.edu.au for help with this site. +The 'Source Only' sites may also contain binary packages as we are now +including them on samba.anu.edu.au/pub/samba/Binary_Packages + Mirror sites include: -Source Only -=========== ---- Australia --- +--- Austria --- + ftp://gd.tuwien.ac.at/pub/infosys/servers/samba/sources/ +--- Australia --- ftp://samba.anu.edu.au/pub/samba/ - ftp://nimbus.anu.edu.au/pub/tridge/samba/ ftp://choc.satech.net.au/pub/samba/ --- USA Educational --- + ftp://sunsite.unc.edu/pub/packages/samba/sources/ ftp://ftp.micro.caltech.edu/pub/samba/ ftp://ftp.cs.ucr.edu/pub/software/samba/ - ftp://sunsite.unc.edu/pub/Linux/system/Network/samba/ --- Czech Republic --- ftp://sunsite.mff.cuni.cz/Net/Protocols/Samba/ +--- Denmark --- + ftp://sunsite.auc.dk/pub/unix/networking/samba/ +--- Finland --- + ftp://nic.funet.fi/pub/mirrors/samba.anu.edu.au/ --- Germany --- ftp://ftp.uni-trier.de/pub/unix/network/samba/ - ftp://ftp.gwdg.de/pub/server/samba/ + ftp://ftp.gwdg.de/pub/server/samba/ +--- Greece --- + ftp://ftp.ntua.gr/pub/net/samba/ +--- Italy --- + ftp://volftp.tin.it/mirror/samba/pub/samba/ + http://www.inferentia.it/archives/samba/ (no binaries) --- Japan --- ftp://ring.asahi-net.or.jp/archives/net/samba/ ftp://ring.aist.go.jp/archives/net/samba/ @@ -28,26 +39,17 @@ Source Only ftp://ftp.gbnet.net/pub/samba/ ftp://ftp.ntrl.net/pub/mirror/samba/ ftp://despair.capecod.net/pub/Samba/ ---- Portugal --- +--- Poland --- + ftp://giswitch.sggw.waw.pl/pub/unix/samba/ +--- Potugal --- ftp://ftp.ua.pt/pub/misc/samba/ +--- Romania --- + ftp://ftp.romus.ro/pub/Linux/Network/samba/ --- Russian Federation --- ftp://ftp.uic.nsu.ru/pub/vendors/samba/ ---- United Kingdom --- - ftp://ftp.demon.co.uk/pub/mirrors/samba/ - ftp://src.doc.ic.ac.uk/packages/samba/ - -Sources & Binaries -================== ---- Austria --- - ftp://gd.tuwien.ac.at/pub/infosys/servers/samba/ ---- Denmark --- - ftp://sunsite.auc.dk/pub/unix/networking/samba/ ---- USA Educational --- - ftp://sunsite.unc.edu/pub/packages/samba/ ---- Italy --- - http://www.inferentia.it/archives/samba/ --- United Kingdom --- ftp://sunsite.doc.ic.ac.uk/packages/samba/ + ftp://ftp.demon.co.uk/pub/mirrors/samba/ SCO binaries available from: http://www.math.u-szeged.hu/hardsoft/hsdetail.htm @@ -75,7 +77,6 @@ There are several others. Give archie a try. Http sites include: =================== -http://samba.canberra.edu.au/pub/samba -http://www.choc.satech.net.au/pub/samba/ - +http://samba.anu.edu.au/samba +Japanese - http://samba.bento.ad.jp/ diff --git a/docs/textdocs/UNIX_INSTALL.txt b/docs/textdocs/UNIX_INSTALL.txt index c189482ca41..9a5eb04faaf 100644 --- a/docs/textdocs/UNIX_INSTALL.txt +++ b/docs/textdocs/UNIX_INSTALL.txt @@ -15,7 +15,7 @@ try something like: Unfortunately, having said this, the man pages are sadly out of date and really need more effort to maintain them. Other sources of information -are pointed to by the Samba web site, http://samba.canberra.edu.au/pub/samba. +are pointed to by the Samba web site, http://samba.anu.edu.au/samba/. STEP 1. Building the binaries -- cgit From d3fa968b6aa0b7eebf25016df16d626421ef00f3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 13:06:59 +0000 Subject: check for EPERM or EACCESS in file_utime() only use lp_alternate_permissions() for display purposes --- source/smbd/server.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/source/smbd/server.c b/source/smbd/server.c index 0eaa708520f..27f8b76029c 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -312,7 +312,10 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) if(sys_utime(fname, times) == 0) return 0; - if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum))) + if((errno != EPERM) && (errno != EACCESS)) + return -1; + + if(!lp_dos_filetimes(SNUM(cnum))) return -1; /* We have permission (given by the Samba admin) to @@ -325,20 +328,18 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) return -1; /* Check if we have write access. */ - if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) - { - if (((sb.st_mode & S_IWOTH) || - Connections[cnum].admin_user || - ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || - ((sb.st_mode & S_IWGRP) && - in_group(sb.st_gid,current_user.gid, - current_user.ngroups,current_user.igroups)))) - { - /* We are allowed to become root and change the filetime. */ - become_root(False); - ret = sys_utime(fname, times); - unbecome_root(False); - } + if (CAN_WRITE(cnum)) { + if (((sb.st_mode & S_IWOTH) || + Connections[cnum].admin_user || + ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) || + ((sb.st_mode & S_IWGRP) && + in_group(sb.st_gid,current_user.gid, + current_user.ngroups,current_user.igroups)))) { + /* We are allowed to become root and change the filetime. */ + become_root(False); + ret = sys_utime(fname, times); + unbecome_root(False); + } } return ret; -- cgit From 9f2a49a12454dd970f10b50f24b8577d0c9361ed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell <tridge@samba.org> Date: Tue, 21 Oct 1997 13:16:56 +0000 Subject: for 1.9.17 as well --- source/smbd/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/smbd/server.c b/source/smbd/server.c index 27f8b76029c..7d18a070cbe 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -312,7 +312,7 @@ int file_utime(int cnum, char *fname, struct utimbuf *times) if(sys_utime(fname, times) == 0) return 0; - if((errno != EPERM) && (errno != EACCESS)) + if((errno != EPERM) && (errno != EACCES)) return -1; if(!lp_dos_filetimes(SNUM(cnum))) -- cgit From 00219573fee86dde0d56251b30b12c118b9f4ef8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison <jra@samba.org> Date: Tue, 21 Oct 1997 16:34:56 +0000 Subject: Updated for p4 release. Jeremy. --- WHATSNEW.txt | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 4fa0151c204..83f4aae3081 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,5 +1,5 @@ - WHATS NEW IN 1.9.17p4 - October 20th 1997 - =========================================== + WHATS NEW IN 1.9.17p4 - October 21st. 1997 + ========================================== Update release: Samba - version 1.9.17p4. ----------------------------------------- @@ -12,10 +12,22 @@ Here are a list of the fixes in this release (the fixes introduced between 1.9.17p3 and 1.9.17p4) : 1). Fix in nmbd for Windows 95 machines hanging on logout ! -2). Fix so nmbd ignores loopback packets. -3). New option 'dos filetimes' to fix UTIME_WORKAROUND problem. -4). Fix for nmbd ignoring WINS negative responses. -5). New PAM support from RedHat for new PAM version. +2). Fix for slow share mode code leaving zero length share + files. +3). Fix for security = server, some broken NT4.x servers don't + set the guest bit on connections. New code to check logged + in user matches requested user. +4). Fix for security = server. Problem with previous workaround + which caused machine logon restrictions on an NT server to fail. + This code has been completely re-written. +5). New option 'dos filetimes' to fix UTIME_WORKAROUND problem. +6). Fix so nmbd ignores loopback packets. +7). Fix for nmbd ignoring WINS negative responses. +8). New PAM support from RedHat for new PAM version. +9). Memory leak fix when files included from an smb.conf + are changed. +10). Client now logs when connecting as 'guest'. +11). Updated documentation. Reporting bugs -------------- -- cgit From 460186a1b4de8ddeebe9d37faafd9b5b321ee493 Mon Sep 17 00:00:00 2001 From: Samba Release Account <samba-bugs@samba.org> Date: Tue, 21 Oct 1997 16:43:43 +0000 Subject: preparing for release of 1.9.17p4 --- docs/manpages/nmbd.8 | 2 +- docs/manpages/samba.7 | 2 +- docs/manpages/smb.conf.5 | 2 +- docs/manpages/smbclient.1 | 2 +- docs/manpages/smbd.8 | 2 +- docs/manpages/smbpasswd.8 | 2 +- docs/manpages/smbrun.1 | 2 +- docs/manpages/smbstatus.1 | 2 +- docs/manpages/smbtar.1 | 2 +- docs/manpages/testparm.1 | 2 +- docs/manpages/testprns.1 | 2 +- docs/textdocs/Application_Serving.txt | 3 +++ docs/textdocs/BROWSING.txt | 3 +++ docs/textdocs/BUGS.txt | 3 +++ docs/textdocs/DIAGNOSIS.txt | 3 +++ docs/textdocs/DNIX.txt | 3 +++ docs/textdocs/DOMAIN.txt | 3 +++ docs/textdocs/DOMAIN_CONTROL.txt | 3 +++ docs/textdocs/ENCRYPTION.txt | 3 +++ docs/textdocs/Faxing.txt | 3 +++ docs/textdocs/GOTCHAS.txt | 3 +++ docs/textdocs/HINTS.txt | 3 +++ docs/textdocs/MIRRORS.txt | 3 +++ docs/textdocs/NetBIOS.txt | 3 +++ docs/textdocs/OS2-Client-HOWTO.txt | 3 +++ docs/textdocs/Passwords.txt | 3 +++ docs/textdocs/Printing.txt | 3 +++ docs/textdocs/SCO.txt | 3 +++ docs/textdocs/Speed.txt | 3 +++ docs/textdocs/Support.txt | 3 +++ docs/textdocs/Tracing.txt | 3 +++ docs/textdocs/UNIX-SMB.txt | 3 +++ docs/textdocs/UNIX_INSTALL.txt | 3 +++ docs/textdocs/Win95.txt | 3 +++ docs/textdocs/WinNT.txt | 3 +++ docs/textdocs/security_level.txt | 3 +++ source/include/version.h | 2 +- 37 files changed, 87 insertions(+), 12 deletions(-) diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8 index 148e53478c2..100cbcc5087 100644 --- a/docs/manpages/nmbd.8 +++ b/docs/manpages/nmbd.8 @@ -1,4 +1,4 @@ -.TH NMBD 8 nmbd nmbd +.TH NMBD 8 "22 Oct 1997" "nmbd 1.9.17p4" .SH NAME nmbd \- provide netbios nameserver support to clients .SH SYNOPSIS diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7 index 7260cbad396..a15c4a0041e 100644 --- a/docs/manpages/samba.7 +++ b/docs/manpages/samba.7 @@ -1,4 +1,4 @@ -.TH SAMBA 7 Samba Samba +.TH SAMBA 7 "22 Oct 1997" "samba 1.9.17p4" .SH NAME Samba \- a LanManager like fileserver for UNIX .SH SYNOPSIS diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index 1e66ccb44c4..1bd5ab26cf4 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -1,4 +1,4 @@ -.TH SMB.CONF 5 smb.conf smb.conf +.TH SMB.CONF 5 "22 Oct 1997" "smb.conf 1.9.17p4" .SH NAME smb.conf \- configuration file for smbd .SH SYNOPSIS diff --git a/docs/manpages/smbclient.1 b/docs/manpages/smbclient.1 index 6ae454f2f24..e8c7c291e37 100644 --- a/docs/manpages/smbclient.1 +++ b/docs/manpages/smbclient.1 @@ -1,4 +1,4 @@ -.TH SMBCLIENT 1 smbclient smbclient +.TH SMBCLIENT 1 "22 Oct 1997" "smbclient 1.9.17p4" .SH NAME smbclient \- ftp-like Lan Manager client program .SH SYNOPSIS diff --git a/docs/manpages/smbd.8 b/docs/manpages/smbd.8 index 6c26c83c0d1..8f9aeb54a91 100644 --- a/docs/manpages/smbd.8 +++ b/docs/manpages/smbd.8 @@ -1,4 +1,4 @@ -.TH SMBD 8 smbd smbd +.TH SMBD 8 "22 Oct 1997" "smbd 1.9.17p4" .SH NAME smbd \- provide SMB (aka LanManager) services to clients .SH SYNOPSIS diff --git a/docs/manpages/smbpasswd.8 b/docs/manpages/smbpasswd.8 index 176534b04f6..ff4c10a721a 100644 --- a/docs/manpages/smbpasswd.8 +++ b/docs/manpages/smbpasswd.8 @@ -1,4 +1,4 @@ -.TH SMBPASSWD 1 smbpasswd smbpasswd +.TH SMBPASSWD 8 "22 Oct 1997" "smbpasswd 1.9.17p4" .SH NAME smbpasswd \- change a users smb password in the smbpasswd file. .SH SYNOPSIS diff --git a/docs/manpages/smbrun.1 b/docs/manpages/smbrun.1 index bc265ebf7f5..194ef45457f 100644 --- a/docs/manpages/smbrun.1 +++ b/docs/manpages/smbrun.1 @@ -1,4 +1,4 @@ -.TH SMBRUN 1 smbrun smbrun +.TH SMBRUN 1 "22 Oct 1997" "smbrun 1.9.17p4" .SH NAME smbrun \- interface program between smbd and external programs .SH SYNOPSIS diff --git a/docs/manpages/smbstatus.1 b/docs/manpages/smbstatus.1 index e59f815b78b..c28f7282611 100644 --- a/docs/manpages/smbstatus.1 +++ b/docs/manpages/smbstatus.1 @@ -1,4 +1,4 @@ -.TH SMBSTATUS 1 smbstatus smbstatus +.TH SMBSTATUS 1 "22 Oct 1997" "smbstatus 1.9.17p4" .SH NAME smbstatus \- report on current Samba connections .SH SYNOPSIS diff --git a/docs/manpages/smbtar.1 b/docs/manpages/smbtar.1 index a03b8a6a668..b21af230962 100644 --- a/docs/manpages/smbtar.1 +++ b/docs/manpages/smbtar.1 @@ -1,4 +1,4 @@ -.TH SMBTAR 1 smbtar smbtar +.TH SMBTAR 1 "22 Oct 1997" "smbtar 1.9.17p4" .SH NAME smbtar \- shell script for backing up SMB shares directly to UNIX tape drive .SH SYNOPSIS diff --git a/docs/manpages/testparm.1 b/docs/manpages/testparm.1 index 0b6e6e84c0b..812d417ead8 100644 --- a/docs/manpages/testparm.1 +++ b/docs/manpages/testparm.1 @@ -1,4 +1,4 @@ -.TH TESTPARM 1 testparm testparm +.TH TESTPARM 1 "22 Oct 1997" "testparm 1.9.17p4" .SH NAME testparm \- check an smbd configuration file for internal correctness .SH SYNOPSIS diff --git a/docs/manpages/testprns.1 b/docs/manpages/testprns.1 index 9819a679d84..bc0744d14c7 100644 --- a/docs/manpages/testprns.1 +++ b/docs/manpages/testprns.1 @@ -1,4 +1,4 @@ -.TH TESTPRNS 1 testprns testprns +.TH TESTPRNS 1 "22 Oct 1997" "testprns 1.9.17p4" .SH NAME testprns \- check printer name for validity with smbd .SH SYNOPSIS diff --git a/docs/textdocs/Application_Serving.txt b/docs/textdocs/Application_Serving.txt index 5a17b64b030..d228b5cbd84 100644 --- a/docs/textdocs/Application_Serving.txt +++ b/docs/textdocs/Application_Serving.txt @@ -1,3 +1,6 @@ +!== +!== Application_Serving.txt for Samba release 1.9.17p4 22 Oct 1997 +!== January 7, 1997 Updated: June 27, 1997 Contributor: John H Terpstra <samba-bugs@samba.anu.edu.au> diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt index 4e0a49f2202..84aed64b081 100644 --- a/docs/textdocs/BROWSING.txt +++ b/docs/textdocs/BROWSING.txt @@ -1,3 +1,6 @@ +!== +!== BROWSING.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Author/s: Many (Thanks to Luke, Jeremy, Andrew, etc.) Updated: June 29, 1997 Status: Current - For VERY Advanced Users ONLY diff --git a/docs/textdocs/BUGS.txt b/docs/textdocs/BUGS.txt index 5fc069371b3..f5352e976ea 100644 --- a/docs/textdocs/BUGS.txt +++ b/docs/textdocs/BUGS.txt @@ -1,3 +1,6 @@ +!== +!== BUGS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Samba Team Updated: June 27, 1997 diff --git a/docs/textdocs/DIAGNOSIS.txt b/docs/textdocs/DIAGNOSIS.txt index 18259ecc94f..06c4ce8b2fd 100644 --- a/docs/textdocs/DIAGNOSIS.txt +++ b/docs/textdocs/DIAGNOSIS.txt @@ -1,3 +1,6 @@ +!== +!== DIAGNOSIS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell Updated: October 14, 1997 diff --git a/docs/textdocs/DNIX.txt b/docs/textdocs/DNIX.txt index 51005e6ec8c..2c2386a1ef6 100644 --- a/docs/textdocs/DNIX.txt +++ b/docs/textdocs/DNIX.txt @@ -1,3 +1,6 @@ +!== +!== DNIX.txt for Samba release 1.9.17p4 22 Oct 1997 +!== DNIX has a problem with seteuid() and setegid(). These routines are needed for Samba to work correctly, but they were left out of the DNIX C library for some reason. diff --git a/docs/textdocs/DOMAIN.txt b/docs/textdocs/DOMAIN.txt index 3cd8a125b7b..49250239db3 100644 --- a/docs/textdocs/DOMAIN.txt +++ b/docs/textdocs/DOMAIN.txt @@ -1,3 +1,6 @@ +!== +!== DOMAIN.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Samba Team Updated: June 27, 1997 diff --git a/docs/textdocs/DOMAIN_CONTROL.txt b/docs/textdocs/DOMAIN_CONTROL.txt index 0b077320cdb..37d7a9dd5f9 100644 --- a/docs/textdocs/DOMAIN_CONTROL.txt +++ b/docs/textdocs/DOMAIN_CONTROL.txt @@ -1,3 +1,6 @@ +!== +!== DOMAIN_CONTROL.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Initial Release: August 22, 1996 Contributor: John H Terpstra <samba-bugs@samba.anu.edu.au> Copyright (C) 1996-1997 - John H Terpstra diff --git a/docs/textdocs/ENCRYPTION.txt b/docs/textdocs/ENCRYPTION.txt index 69dd49b257a..f06972b45ca 100644 --- a/docs/textdocs/ENCRYPTION.txt +++ b/docs/textdocs/ENCRYPTION.txt @@ -1,3 +1,6 @@ +!== +!== ENCRYPTION.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Jeremy Allison <samba-bugs@samba.anu.edu.au> Updated: June 27, 1997 Note: Please refer to WinNT.txt also diff --git a/docs/textdocs/Faxing.txt b/docs/textdocs/Faxing.txt index 0703d75cc35..cb8f7722ca5 100644 --- a/docs/textdocs/Faxing.txt +++ b/docs/textdocs/Faxing.txt @@ -1,3 +1,6 @@ +!== +!== Faxing.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Gerhard Zuber <zuber@berlin.snafu.de> Date: August 5th 1997. Status: Current diff --git a/docs/textdocs/GOTCHAS.txt b/docs/textdocs/GOTCHAS.txt index bc5c6dae853..f0b73dd164a 100644 --- a/docs/textdocs/GOTCHAS.txt +++ b/docs/textdocs/GOTCHAS.txt @@ -1,3 +1,6 @@ +!== +!== GOTCHAS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== This file lists Gotchas to watch out for: ========================================================================= Item Number: 1.0 diff --git a/docs/textdocs/HINTS.txt b/docs/textdocs/HINTS.txt index f5781ee4232..e809238c9e6 100644 --- a/docs/textdocs/HINTS.txt +++ b/docs/textdocs/HINTS.txt @@ -1,3 +1,6 @@ +!== +!== HINTS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Many Updated: Not for a long time! diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt index 2ce18b6d5b0..8c3697a3eab 100755 --- a/docs/textdocs/MIRRORS.txt +++ b/docs/textdocs/MIRRORS.txt @@ -1,3 +1,6 @@ +!== +!== MIRRORS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== The main Samba ftp site is samba.anu.edu.au in pub/samba/. Contact samba-bugs@samba.anu.edu.au for help with this site. diff --git a/docs/textdocs/NetBIOS.txt b/docs/textdocs/NetBIOS.txt index 415aa34beb9..a306cdf403c 100644 --- a/docs/textdocs/NetBIOS.txt +++ b/docs/textdocs/NetBIOS.txt @@ -1,3 +1,6 @@ +!== +!== NetBIOS.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: lkcl - samba-bugs@arvidsjaur.anu.edu.au Copyright 1997 Luke Kenneth Casson Leighton Date: March 1997 diff --git a/docs/textdocs/OS2-Client-HOWTO.txt b/docs/textdocs/OS2-Client-HOWTO.txt index cf3033956ea..e627377c45b 100644 --- a/docs/textdocs/OS2-Client-HOWTO.txt +++ b/docs/textdocs/OS2-Client-HOWTO.txt @@ -1,3 +1,6 @@ +!== +!== OS2-Client-HOWTO.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Q. How can I configure OS/2 Warp Connect or OS/2 Warp 4 as a client for Samba? diff --git a/docs/textdocs/Passwords.txt b/docs/textdocs/Passwords.txt index f76010c4608..116109ffe0b 100644 --- a/docs/textdocs/Passwords.txt +++ b/docs/textdocs/Passwords.txt @@ -1,3 +1,6 @@ +!== +!== Passwords.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Unknown Date: Unknown Status: Current diff --git a/docs/textdocs/Printing.txt b/docs/textdocs/Printing.txt index e8a2d2ad27f..c0cb670397a 100644 --- a/docs/textdocs/Printing.txt +++ b/docs/textdocs/Printing.txt @@ -1,3 +1,6 @@ +!== +!== Printing.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Unknown <samba-bugs@samba.anu.edu.au> Date: Unknown Status: Current diff --git a/docs/textdocs/SCO.txt b/docs/textdocs/SCO.txt index 7c01aa57c6c..ae17a423797 100644 --- a/docs/textdocs/SCO.txt +++ b/docs/textdocs/SCO.txt @@ -1,3 +1,6 @@ +!== +!== SCO.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Geza Makay <makayg@math.u-szeged.hu> Date: Unknown Status: Obsolete - Dates to SCO Unix v3.2.4 approx. diff --git a/docs/textdocs/Speed.txt b/docs/textdocs/Speed.txt index b11885fc377..df7d00b12f5 100644 --- a/docs/textdocs/Speed.txt +++ b/docs/textdocs/Speed.txt @@ -1,3 +1,6 @@ +!== +!== Speed.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell Date: January 1995 Status: Current diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt index ee8e1b6befa..ab430655e28 100644 --- a/docs/textdocs/Support.txt +++ b/docs/textdocs/Support.txt @@ -1,3 +1,6 @@ +!== +!== Support.txt for Samba release 1.9.17p4 22 Oct 1997 +!== The Samba Consultants List ========================== diff --git a/docs/textdocs/Tracing.txt b/docs/textdocs/Tracing.txt index d8b38378228..e3ff162d798 100644 --- a/docs/textdocs/Tracing.txt +++ b/docs/textdocs/Tracing.txt @@ -1,3 +1,6 @@ +!== +!== Tracing.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au> Date: Old Status: Questionable diff --git a/docs/textdocs/UNIX-SMB.txt b/docs/textdocs/UNIX-SMB.txt index ec2e657c052..b9185063cb6 100644 --- a/docs/textdocs/UNIX-SMB.txt +++ b/docs/textdocs/UNIX-SMB.txt @@ -1,3 +1,6 @@ +!== +!== UNIX-SMB.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au> Date: April 1995 diff --git a/docs/textdocs/UNIX_INSTALL.txt b/docs/textdocs/UNIX_INSTALL.txt index 9a5eb04faaf..b3e66ad41b8 100644 --- a/docs/textdocs/UNIX_INSTALL.txt +++ b/docs/textdocs/UNIX_INSTALL.txt @@ -1,3 +1,6 @@ +!== +!== UNIX_INSTALL.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au> Date: Unknown Status: Current diff --git a/docs/textdocs/Win95.txt b/docs/textdocs/Win95.txt index 69330c512d4..8c1023b78be 100644 --- a/docs/textdocs/Win95.txt +++ b/docs/textdocs/Win95.txt @@ -1,3 +1,6 @@ +!== +!== Win95.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Copyright (C) 1997 - Samba-Team Contributed Date: August 20, 1997 Last Update: August 20, 1997 diff --git a/docs/textdocs/WinNT.txt b/docs/textdocs/WinNT.txt index d85f9966bc7..b498168dd85 100644 --- a/docs/textdocs/WinNT.txt +++ b/docs/textdocs/WinNT.txt @@ -1,3 +1,6 @@ +!== +!== WinNT.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributors: Various Password Section - Copyright (C) 1997 - John H Terpstra Printing Section - Copyright (C) 1997 - Matthew Harrell diff --git a/docs/textdocs/security_level.txt b/docs/textdocs/security_level.txt index fac446fda8e..7880fd2bb23 100644 --- a/docs/textdocs/security_level.txt +++ b/docs/textdocs/security_level.txt @@ -1,3 +1,6 @@ +!== +!== security_level.txt for Samba release 1.9.17p4 22 Oct 1997 +!== Contributor: Andrew Tridgell Updated: June 27, 1997 Status: Current diff --git a/source/include/version.h b/source/include/version.h index 7bea7836bc6..e2a81e5b74c 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.17p3" +#define VERSION "1.9.17p4" -- cgit