summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/nameserv.h41
-rw-r--r--source3/include/proto.h14
-rw-r--r--source3/include/smb.h15
-rw-r--r--source3/nameannounce.c8
-rw-r--r--source3/namedbwork.c4
-rw-r--r--source3/nameelect.c379
-rw-r--r--source3/namelogon.c77
-rw-r--r--source3/namepacket.c5
-rw-r--r--source3/nameserv.c61
-rw-r--r--source3/namework.c8
-rw-r--r--source3/nmbd/nmbd.c3
-rw-r--r--source3/smbd/ipc.c472
-rw-r--r--source3/smbd/server.c57
13 files changed, 795 insertions, 349 deletions
diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h
index 7302f09e5d..75461ce5e6 100644
--- a/source3/include/nameserv.h
+++ b/source3/include/nameserv.h
@@ -73,7 +73,8 @@
/* server type identifiers */
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
-#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL)
+#define AM_DOMMST(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER)
+#define AM_DOMMEM(work) (work->ServerType & SV_TYPE_DOMAIN_MEMBER)
/* microsoft browser NetBIOS name */
#define MSBROWSE "\001\002__MSBROWSE__\002"
@@ -85,16 +86,27 @@
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};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
+
enum master_state
{
- MST_NONE,
- MST_WON,
+ MST_POTENTIAL,
+ MST_BACK,
MST_MSB,
- MST_BROWSER,
- MST_DOMAIN_NONE,
- MST_DOMAIN_MEM,
- MST_DOMAIN_TST,
- MST_DOMAIN
+ MST_BROWSER
+};
+
+enum domain_state
+{
+ DOMAIN_NONE,
+ DOMAIN_WAIT,
+ DOMAIN_MST
+};
+
+enum logon_state
+{
+ LOGON_NONE,
+ LOGON_WAIT,
+ LOGON_SRV
};
enum state_type
@@ -179,8 +191,14 @@ struct work_record
struct server_record *serverlist;
- /* stage of development from non-master to master browser / domain master */
- enum master_state state;
+ /* stage of development from non-local-master up to local-master browser */
+ enum master_state mst_state;
+
+ /* stage of development from non-domain-master to domain master browser */
+ enum domain_state dom_state;
+
+ /* stage of development from non-logon-server to logon server */
+ enum logon_state log_state;
/* work group info */
fstring work_group;
@@ -367,6 +385,9 @@ struct packet_struct
/* broadcast packet announcement intervals, in minutes */
+/* attempt to add domain logon and domain master names */
+#define CHECK_TIME_ADD_DOM_NAMES 5
+
/* search for master browsers of workgroups samba knows about,
except default */
#define CHECK_TIME_MST_BROWSE 5
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 2cd8cfe2a8..bbfcad78f9 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -411,8 +411,14 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
void name_unregister_work(struct subnet_record *d, char *name, int name_type);
void name_register_work(struct subnet_record *d, char *name, int name_type,
int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast);
-void become_master(struct subnet_record *d, struct work_record *work);
-void become_nonmaster(struct subnet_record *d, struct work_record *work,
+void become_local_master(struct subnet_record *d, struct work_record *work);
+void become_domain_master(struct subnet_record *d, struct work_record *work);
+void become_logon_server(struct subnet_record *d, struct work_record *work);
+void unbecome_local_master(struct subnet_record *d, struct work_record *work,
+ int remove_type);
+void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
+ int remove_type);
+void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
int remove_type);
void run_elections(time_t t);
void process_election(struct packet_struct *p,char *buf);
@@ -436,7 +442,8 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
void queue_packet(struct packet_struct *packet);
void run_packet_queue();
void listen_for_packets(BOOL run_election);
-BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
+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);
@@ -469,6 +476,7 @@ struct response_record *queue_netbios_packet(struct subnet_record *d,
void remove_name_entry(struct subnet_record *d, char *name,int type);
void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags);
+void add_domain_names(time_t t);
void add_my_names(void);
void remove_my_names();
void refresh_my_names(time_t t);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index eea5b5bc8c..e9d74befc2 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -797,6 +797,21 @@ char *Strstr(char *s, char *p);
/* what server type are we currently */
+/* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */
+
+#define CAP_RAW_MODE 0x0001
+#define CAP_MPX_MODE 0x0002
+#define CAP_UNICODE 0x0004
+#define CAP_LARGE_FILES 0x0008
+#define CAP_NT_SMBS 0x0010
+#define CAP_RPC_REMOTE_APIS 0x0020
+#define CAP_STATUS32 0x0040
+#define CAP_LEVEL_II_OPLOCKS 0x0080
+#define CAP_LOCK_AND_READ 0x0100
+#define CAP_NT_FIND 0x0200
+#define CAP_DFS 0x1000
+#define CAP_LARGE_READX 0x4000
+
/* protocol types. It assumes that higher protocols include lower protocols
as subsets */
enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1};
diff --git a/source3/nameannounce.c b/source3/nameannounce.c
index 1dadc0132c..990be00602 100644
--- a/source3/nameannounce.c
+++ b/source3/nameannounce.c
@@ -79,7 +79,8 @@ 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(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False, BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
}
@@ -106,7 +107,8 @@ void do_announce_request(char *info, char *to_name, int announce_type,
strupper(p);
p = skip_string(p,1);
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
}
@@ -172,7 +174,7 @@ void do_announce_host(int command,
debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
/* send the announcement */
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf),
from_name, to_name,
from_type, to_type,
diff --git a/source3/namedbwork.c b/source3/namedbwork.c
index 04f2103254..0cfc47c41a 100644
--- a/source3/namedbwork.c
+++ b/source3/namedbwork.c
@@ -91,7 +91,9 @@ static struct work_record *make_workgroup(char *name)
work->ElectionCount = 0;
work->needelection = False;
work->needannounce = True;
- work->state = MST_NONE;
+ work->mst_state = MST_POTENTIAL;
+ work->dom_state = DOMAIN_NONE;
+ work->log_state = LOGON_NONE;
/* make sure all token representations of workgroups are unique */
diff --git a/source3/nameelect.c b/source3/nameelect.c
index 9a15c0b112..9254e44712 100644
--- a/source3/nameelect.c
+++ b/source3/nameelect.c
@@ -51,6 +51,7 @@ extern struct subnet_record *subnetlist;
extern uint16 nb_type; /* samba's NetBIOS name type */
+
/*******************************************************************
occasionally check to see if the master browser is around
******************************************************************/
@@ -167,7 +168,8 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
strupper(p);
p = skip_string(p,1);
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
}
@@ -183,26 +185,39 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion,
void name_unregister_work(struct subnet_record *d, char *name, int name_type)
{
struct work_record *work;
+ int remove_type_local = 0;
+ int remove_type_domain = 0;
+ int remove_type_logon = 0;
remove_netbios_name(d,name,name_type,SELF,ipzero);
if (!(work = find_workgroupstruct(d, name, False))) return;
- if (ms_browser_name(name, name_type) ||
- (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
- (name_type == 0x1d || name_type == 0x1b)))
+ /* work out what to unbecome, from the name type being removed */
+
+ if (ms_browser_name(name, name_type))
+ {
+ remove_type_local |= SV_TYPE_MASTER_BROWSER;
+ }
+ if (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
+ name_type == 0x1d)
+ {
+ remove_type_local |= SV_TYPE_MASTER_BROWSER;
+ }
+ if (AM_DOMMST(work) && strequal(name, lp_workgroup()) == 0 &&
+ name_type == 0x1b)
{
- int remove_type = 0;
-
- if (ms_browser_name(name, name_type))
- remove_type = SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
- if (name_type == 0x1d)
- remove_type = SV_TYPE_MASTER_BROWSER;
- if (name_type == 0x1b)
- remove_type = SV_TYPE_DOMAIN_MASTER;
-
- become_nonmaster(d, work, remove_type);
+ remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
}
+ if (AM_DOMMEM(work) && strequal(name, lp_workgroup()) == 0 &&
+ name_type == 0x1c)
+ {
+ remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
+ }
+
+ if (remove_type_local ) unbecome_local_master (d, work, remove_type_local );
+ if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain);
+ if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon );
}
@@ -227,12 +242,28 @@ void name_register_work(struct subnet_record *d, char *name, int name_type,
if (work)
{
- if (work->state != MST_NONE)
+ if (work->mst_state != MST_POTENTIAL)
{
- /* samba is in the process of working towards master browser-ness.
+ /* samba is working towards local master browser-ness.
initiate the next stage.
*/
- become_master(d, work);
+ become_local_master(d, work);
+ return;
+ }
+ if (work->dom_state != DOMAIN_NONE)
+ {
+ /* samba is working towards domain master browser-ness.
+ initiate the next stage.
+ */
+ become_domain_master(d, work);
+ return;
+ }
+ if (work->log_state != LOGON_NONE)
+ {
+ /* samba is working towards domain master browser-ness.
+ initiate the next stage.
+ */
+ become_logon_server(d, work);
return;
}
}
@@ -241,29 +272,28 @@ void name_register_work(struct subnet_record *d, char *name, int name_type,
/*******************************************************************
- become the master browser.
+ become the local master browser.
this is done in stages. note that this could take a while,
particularly on a broadcast subnet, as we have to wait for
the implicit registration of each name to be accepted.
- as each name is successfully registered, become_master() is
+ as each name is successfully registered, become_local_master() is
called again, in order to initiate the next stage. see
dead_netbios_entry() - deals with implicit name registration
and response_name_reg() - deals with explicit registration
with a WINS server.
- stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1.
- stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d)
- stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b)
- stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...)
+ stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
+ stage 2: was MST_BACK - go to MST_MSB and register WORKGROUP(0x1d)
+ stage 3: was MST_MSB - go to MST_BROWSER and stay there
XXXX note: this code still does not cope with the distinction
between different types of nodes, particularly between M and P
nodes. that comes later.
******************************************************************/
-void become_master(struct subnet_record *d, struct work_record *work)
+void become_local_master(struct subnet_record *d, struct work_record *work)
{
/* domain type must be limited to domain enum + server type. it must
not have SV_TYPE_SERVER or anything else with SERVER in it, else
@@ -272,17 +302,17 @@ void become_master(struct subnet_record *d, struct work_record *work)
*/
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
- if (!work) return;
+ if (!work || !d) return;
DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
- work->work_group,inet_ntoa(d->bcast_ip),work->state));
+ work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
- switch (work->state)
+ switch (work->mst_state)
{
- case MST_NONE: /* while we were nothing but a server... */
+ case MST_POTENTIAL: /* while we were nothing but a server... */
{
DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
- work->state = MST_WON; /* ... an election win was successful */
+ work->mst_state = MST_BACK; /* ... an election win was successful */
work->ElectionCriterion |= 0x5;
@@ -294,12 +324,13 @@ void become_master(struct subnet_record *d, struct work_record *work)
add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
- return;
+ break;
}
- case MST_WON: /* while nothing had happened except we won an election... */
+
+ case MST_BACK: /* while nothing had happened except we won an election... */
{
DEBUG(3,("go to second stage: register as master browser\n"));
- work->state = MST_MSB; /* ... registering MSBROWSE was successful */
+ work->mst_state = MST_MSB; /* ... registering MSBROWSE was successful */
/* add server entry on successful registration of MSBROWSE */
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
@@ -308,12 +339,13 @@ void become_master(struct subnet_record *d, struct work_record *work)
add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
/* DON'T do anything else after calling add_my_name_entry() */
- return;
+ break;
}
+
case MST_MSB: /* while we were still only registered MSBROWSE state... */
{
DEBUG(3,("2nd stage complete: registered as master browser\n"));
- work->state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
+ work->mst_state = MST_BROWSER; /* ... registering WORKGROUP(1d) succeeded */
/* update our server status */
work->ServerType |= SV_TYPE_MASTER_BROWSER;
@@ -322,31 +354,70 @@ void become_master(struct subnet_record *d, struct work_record *work)
if (work->serverlist == NULL) /* no servers! */
{
/* ask all servers on our local net to announce to us */
+ /* XXXX OOPS! add_server_entry will always add one entry - our own. */
announce_request(work, d->bcast_ip);
}
break;
- }
+ }
- case MST_BROWSER:
- {
+ case MST_BROWSER:
+ {
/* don't have to do anything: just report success */
DEBUG(3,("3rd stage: become master browser!\n"));
break;
- }
+ }
+ }
+}
- case MST_DOMAIN_NONE:
- {
+
+/*******************************************************************
+ become the domain master browser.
+
+ this is done in stages. note that this could take a while,
+ particularly on a broadcast subnet, as we have to wait for
+ the implicit registration of each name to be accepted.
+
+ as each name is successfully registered, become_domain_master() is
+ called again, in order to initiate the next stage. see
+ dead_netbios_entry() - deals with implicit name registration
+ and response_name_reg() - deals with explicit registration
+ with a WINS server.
+
+ stage 1: was DOMAIN_NONE - go to DOMAIN_MST
+
+ XXXX note: this code still does not cope with the distinction
+ between different types of nodes, particularly between M and P
+ nodes. that comes later.
+
+ ******************************************************************/
+void become_domain_master(struct subnet_record *d, struct work_record *work)
+{
+ /* domain type must be limited to domain enum + server type. it must
+ not have SV_TYPE_SERVER or anything else with SERVER in it, else
+ clients get confused and start thinking this entry is a server
+ not a workgroup
+ */
+
+ if (!work || !d) return;
+
+ DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
+ work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
+
+ switch (work->dom_state)
+ {
+ case DOMAIN_NONE: /* while we were nothing but a server... */
+ {
if (lp_domain_master())
{
- work->state = MST_DOMAIN_MEM; /* ... become domain member */
- DEBUG(3,("domain first stage: register as domain member\n"));
+ DEBUG(3,("go to first stage: register <1b> name\n"));
+ work->dom_state = DOMAIN_WAIT;
- /* add domain member name */
- add_my_name_entry(d,work->work_group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
+ /* XXXX the 0x1b is domain master browser name */
+ add_my_name_entry(d, lp_workgroup(),0x1b,nb_type|NB_ACTIVE|NB_GROUP);
- /* DON'T do anything else after calling add_my_name_entry() */
- return;
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
}
else
{
@@ -354,26 +425,23 @@ void become_master(struct subnet_record *d, struct work_record *work)
}
break;
- }
+ }
- case MST_DOMAIN_MEM:
+ case DOMAIN_WAIT:
{
if (lp_domain_master())
{
- work->state = MST_DOMAIN_TST; /* ... possibly become domain master */
- DEBUG(3,("domain second stage: register as domain master\n"));
-
- if (lp_domain_logons())
- {
- work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
- add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
- }
+ work->dom_state = DOMAIN_MST; /* ... become domain master */
+ DEBUG(3,("domain first stage: register as domain member\n"));
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
+ add_server_entry(d,work,myname,work->ServerType,0,
+ lp_serverstring(),True);
- /* add domain master name */
- add_my_name_entry(d,work->work_group,0x1b,nb_type|NB_ACTIVE );
+ DEBUG(4,("samba is now a domain master\n"));
- /* DON'T do anything else after calling add_my_name_entry() */
- return;
+ break;
}
else
{
@@ -381,108 +449,173 @@ void become_master(struct subnet_record *d, struct work_record *work)
}
break;
+ }
+
+ case DOMAIN_MST:
+ {
+ /* don't have to do anything: just report success */
+ DEBUG(3,("domain second stage: there isn't one!\n"));
+ break;
}
+ }
+}
+
- case MST_DOMAIN_TST: /* while we were still a master browser... */
+/*******************************************************************
+ become a logon server.
+ ******************************************************************/
+void become_logon_server(struct subnet_record *d, struct work_record *work)
+{
+ if (!work || !d) return;
+
+ DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
+ work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
+
+ switch (work->log_state)
+ {
+ case LOGON_NONE: /* while we were nothing but a server... */
{
- /* update our server status */
- if (lp_domain_master())
+ if (lp_domain_logons())
{
- struct subnet_record *d1;
- uint32 update_type = 0;
-
- DEBUG(3,("domain third stage: samba is now a domain master.\n"));
- work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */
+ DEBUG(3,("go to first stage: register <1c> name\n"));
+ work->log_state = LOGON_WAIT;
- update_type |= DFLT_SERVER_TYPE | SV_TYPE_DOMAIN_MASTER |
- SV_TYPE_POTENTIAL_BROWSER;
+ /* XXXX the 0x1c is apparently something to do with domain logons */
+ add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
- work->ServerType |= update_type;
- add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+ {
+ DEBUG(4,("samba not configured as a logon master.\n"));
+ }
+
+ break;
+ }
- for (d1 = subnetlist; d1; d1 = d1->next)
- {
- struct work_record *w;
- if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue;
+ case LOGON_WAIT:
+ {
+ if (lp_domain_logons())
+ {
+ work->log_state = LOGON_SRV; /* ... become logon server */
+ DEBUG(3,("logon second stage: register \n"));
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
+ add_server_entry(d,work,myname,work->ServerType,0,
+ lp_serverstring(),True);
- for (w = d1->workgrouplist; w; w = w->next)
- {
- struct server_record *s = find_server(w, myname);
- if (strequal(w->work_group, work->work_group))
- {
- w->ServerType |= update_type;
- }
- if (s)
- {
- s->serv.type |= update_type;
- DEBUG(4,("found server %s on %s: update to %8x\n",
- s->serv.name, inet_ntoa(d1->bcast_ip),
- s->serv.type));
- }
- }
- }
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+ else
+ {
+ DEBUG(4,("samba not configured as a logon server.\n"));
}
break;
- }
+ }
- case MST_DOMAIN:
- {
- /* don't have to do anything: just report success */
- DEBUG(3,("fifth stage: there isn't one yet!\n"));
+ case LOGON_SRV:
+ {
+ DEBUG(3,("logon third stage: there isn't one!\n"));
break;
- }
+ }
+
}
}
/*******************************************************************
- unbecome the master browser. initates removal of necessary netbios
+ unbecome the local master browser. initates removal of necessary netbios
names, and tells the world that we are no longer a master browser.
+
+ XXXX this _should_ be used to demote to a backup master browser, without
+ going straight to non-master browser. another time.
+
******************************************************************/
-void become_nonmaster(struct subnet_record *d, struct work_record *work,
+void unbecome_local_master(struct subnet_record *d, struct work_record *work,
int remove_type)
{
int new_server_type = work->ServerType;
- DEBUG(2,("Becoming non-master for %s\n",work->work_group));
-
- /* can only remove master or domain types with this function */
- remove_type &= SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
-
- /* unbecome a master browser; unbecome a domain master, too :-( */
- if (remove_type & SV_TYPE_MASTER_BROWSER)
- remove_type |= SV_TYPE_DOMAIN_MASTER;
+ /* can only remove master types with this function */
+ remove_type &= SV_TYPE_MASTER_BROWSER;
new_server_type &= ~remove_type;
- if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)))
+ if (remove_type)
{
+ DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
+
/* no longer a master browser of any sort */
work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
work->ElectionCriterion &= ~0x4;
- work->state = MST_NONE;
+ work->mst_state = MST_POTENTIAL;
/* announce ourselves as no longer active as a master browser. */
announce_server(d, work, work->work_group, myname, 0, 0);
remove_name_entry(d,MSBROWSE ,0x01);
+ remove_name_entry(d,work->work_group,0x1d);
}
+}
+
+
+/*******************************************************************
+ unbecome the domain master browser. initates removal of necessary netbios
+ names, and tells the world that we are no longer a domain browser.
+ ******************************************************************/
+void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
+ int remove_type)
+{
+ int new_server_type = work->ServerType;
+
+ DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
- work->ServerType = new_server_type;
+ /* can only remove master or domain types with this function */
+ remove_type &= SV_TYPE_DOMAIN_MASTER;
- if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
+ new_server_type &= ~remove_type;
+
+ if (remove_type)
{
- if (work->state == MST_DOMAIN)
- work->state = MST_BROWSER;
+ /* no longer a domain master browser of any sort */
+
+ work->dom_state = DOMAIN_NONE;
+
+ /* announce ourselves as no longer active as a master browser. */
+ announce_server(d, work, work->work_group, myname, 0, 0);
remove_name_entry(d,work->work_group,0x1b);
}
+}
+
+
+/*******************************************************************
+ unbecome the logon server. initates removal of necessary netbios
+ names, and tells the world that we are no longer a logon server.
+ ******************************************************************/
+void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
+ int remove_type)
+{
+ int new_server_type = work->ServerType;
+
+ DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
+
+ /* can only remove master or domain types with this function */
+ remove_type &= SV_TYPE_DOMAIN_MEMBER;
- if (!(work->ServerType & SV_TYPE_MASTER_BROWSER))
+ new_server_type &= ~remove_type;
+
+ if (remove_type)
{
- if (work->state >= MST_BROWSER)
- work->state = MST_NONE;
- remove_name_entry(d,work->work_group,0x1d);
+ /* no longer a master browser of any sort */
+
+ work->log_state = LOGON_NONE;
+
+ /* announce ourselves as no longer active as a master browser. */
+ announce_server(d, work, work->work_group, myname, 0, 0);
+ remove_name_entry(d,work->work_group,0x1c);
}
}
@@ -518,9 +651,9 @@ void run_elections(time_t t)
work->work_group,inet_ntoa(d->bcast_ip)));
work->RunningElection = False;
- work->state = MST_NONE;
+ work->mst_state = MST_POTENTIAL;
- become_master(d, work);
+ become_local_master(d, work);
}
}
}
@@ -598,7 +731,7 @@ void process_election(struct packet_struct *p,char *buf)
if (!work->RunningElection) {
work->needelection = True;
work->ElectionCount=0;
- work->state = MST_NONE;
+ work->mst_state = MST_POTENTIAL;
}
} else {
work->needelection = False;
@@ -608,9 +741,7 @@ void process_election(struct packet_struct *p,char *buf)
DEBUG(3,(">>> Lost election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
if (AM_MASTER(work))
- become_nonmaster(d, work,
- SV_TYPE_MASTER_BROWSER|
- SV_TYPE_DOMAIN_MASTER);
+ unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
}
}
}
diff --git a/source3/namelogon.c b/source3/namelogon.c
index aacf32c280..3fab49cedd 100644
--- a/source3/namelogon.c
+++ b/source3/namelogon.c
@@ -54,86 +54,101 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
pstring outbuf;
int code,reply_code;
struct work_record *work;
+ char unknown_byte = 0;
+ uint16 request_count = 0;
+ uint16 token = 0;
if (!d) return;
- if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
- return;
+ if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) return;
- if (!lp_domain_logons()) {
+ if (!lp_domain_logons())
+ {
DEBUG(3,("No domain logons\n"));
return;
}
code = SVAL(buf,0);
- switch (code) {
+ switch (code)
+ {
case 0:
{
char *machine = buf+2;
char *user = skip_string(machine,1);
+ char *tmp;
logname = skip_string(user,1);
- reply_code = 6;
+ tmp = skip_string(logname,1);
+ unknown_byte = CVAL(tmp,0);
+ request_count = SVAL(tmp,1);
+ token = SVAL(tmp,3);
+
+ reply_code = 0x6;
strcpy(reply_name,myname);
strupper(reply_name);
add_slashes = True;
- DEBUG(3,("Domain login request from %s(%s) user=%s\n",
- machine,inet_ntoa(p->ip),user));
- }
+ 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);
- reply_code = 7;
+ token = SVAL(skip_string(logname,1),0);
+
strcpy(reply_name,lp_domain_controller());
- if (!*reply_name) {
+ if (!*reply_name)
+ {
+ /* oo! no domain controller. must be us, then */
strcpy(reply_name,myname);
reply_code = 0xC;
}
- strupper(reply_name);
- DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%2x\n",
- machine,inet_ntoa(p->ip), reply_name, reply_code));
+ 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 (add_slashes) {
+
+ if (token == 0xffff || /* LM 2.0 or later */
+ token == 0xfffe) /* WfWg networking */
+ {
+ if (add_slashes)
+ {
strcpy(q,"\\\\");
q += 2;
}
- StrnCpy(q,reply_name,16);
+ strcpy(q, reply_name);
+ strupper(q);
q = skip_string(q,1);
- if (reply_code == 0xC)
- {
- if ( PTR_DIFF (q,outbuf) & 1 )
+ if (token == 0xffff) /* LM 2.0 or later */
{
- q++;
- }
-
- PutUniCode(q,reply_name);
- q += 2*(strlen(reply_name) + 1);
-
- PutUniCode(q,lp_workgroup());
- q += 2*(strlen(lp_workgroup()) + 1);
-
- SIVAL(q,0,1);
- q += 4;
- SSVAL(q,0,0xFFFF);
+ SSVAL(q,0,token);
q += 2;
}
+ }
SSVAL(q,0,0xFFFF);
q += 2;
- send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
+ 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/source3/namepacket.c b/source3/namepacket.c
index e62f3f00b0..e31d423784 100644
--- a/source3/namepacket.c
+++ b/source3/namepacket.c
@@ -559,7 +559,7 @@ void listen_for_packets(BOOL run_election)
Note that this currently sends all answers to port 138. thats the
wrong things to do! I should send to the requestors port. XXX
**************************************************************************/
-BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
+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)
{
@@ -576,7 +576,8 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
update_name_trn_id();
- dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
+ /* DIRECT GROUP or UNIQUE datagram */
+ dgram->header.msg_type = unique ? 0x10 : 0x11;
dgram->header.flags.node_type = M_NODE;
dgram->header.flags.first = True;
dgram->header.flags.more = False;
diff --git a/source3/nameserv.c b/source3/nameserv.c
index 7353251940..7f1c0fadee 100644
--- a/source3/nameserv.c
+++ b/source3/nameserv.c
@@ -156,6 +156,51 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
/****************************************************************************
+ add the domain logon server and domain master browser names
+
+ this code was written so that several samba servers can co-operate in
+ sharing the task of (one server) being a domain master, and of being
+ domain logon servers.
+
+ **************************************************************************/
+void add_domain_names(time_t t)
+{
+ static time_t lastrun = 0;
+ struct subnet_record *d;
+
+ if (lastrun != 0 && t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60) return;
+ lastrun = t;
+
+ for (d = subnetlist; d; d = d->next)
+ {
+ struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
+ struct nmb_name n;
+
+ if (lp_domain_logons() && work && work->log_state == LOGON_NONE)
+ {
+ make_nmb_name(&n,lp_workgroup(),0x1c,scope);
+ if (!find_name(d->namelist, &n, FIND_SELF))
+ {
+ DEBUG(0,("%s attempting to become logon server for %s %s\n",
+ timestring(), lp_workgroup(), inet_ntoa(d->bcast_ip)));
+ become_logon_server(d, work);
+ }
+ }
+ if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE)
+ {
+ make_nmb_name(&n,lp_workgroup(),0x1b,scope);
+ if (!find_name(d->namelist, &n, FIND_SELF))
+ {
+ DEBUG(1,("%s attempting to become logon server for %s %s\n",
+ timestring(), lp_workgroup(), inet_ntoa(d->bcast_ip)));
+ become_domain_master(d, work);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
add the magic samba names, useful for finding samba servers
**************************************************************************/
void add_my_names(void)
@@ -170,6 +215,7 @@ void add_my_names(void)
for (d = subnetlist; d; d = d->next)
{
BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp);
+ struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
@@ -183,18 +229,13 @@ void add_my_names(void)
add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
- if (lp_domain_logons()) {
- /* XXXX the 0x1c is apparently something to do with domain logons */
- add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+ if (lp_domain_logons() && work && work->log_state == LOGON_NONE)
+ {
+ become_logon_server(d, work);
}
- }
- if (lp_domain_master() && (d = find_subnet(ipgrp)))
- {
- struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True);
- if (work && work->state == MST_NONE)
+ if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE)
{
- work->state = MST_DOMAIN_NONE;
- become_master(d, work);
+ become_domain_master(d, work);
}
}
}
diff --git a/source3/namework.c b/source3/namework.c
index f4a9113cea..20c1050597 100644
--- a/source3/namework.c
+++ b/source3/namework.c
@@ -79,7 +79,8 @@ void reset_server(char *name, int state, struct in_addr ip)
DEBUG(2,("sending reset to %s %s of state %d\n",
name,inet_ntoa(ip),state));
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,name,0x20,0x1d,ip,*iface_ip(ip));
}
@@ -488,7 +489,8 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
int len = PTR_DIFF(p, outbuf);
debug_browse_data(outbuf, len);
}
- send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
myname,theirname,0x0,0x0,ip,*iface_ip(ip));
}
@@ -570,7 +572,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
{
if (AM_MASTER(work))
{
- become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
+ unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
}
}
}
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index 58953bcd9d..e45facdc2e 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -300,9 +300,7 @@ static void process(void)
run_elections(t);
announce_host(t);
-
announce_master(t);
-
announce_remote(t);
query_refresh_names(t);
@@ -314,6 +312,7 @@ static void process(void)
write_browse_list(t);
do_browser_lists(t);
check_master_browser(t);
+ add_domain_names(t);
}
}
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index ccb2f3dd52..9f8369912c 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -1,3 +1,4 @@
+
/*
Unix SMB/Netbios implementation.
Version 1.9.
@@ -1672,7 +1673,8 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
for (i=0;i<count;i++)
- if (strequal(servers[i].name,local_machine)) {
+ if (strequal(servers[i].name,local_machine))
+ {
servertype = servers[i].type;
strcpy(comment,servers[i].comment);
}
@@ -1742,8 +1744,10 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
p = *rdata;
p2 = p + 22;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
+
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
strcpy(p2,local_machine);
+ strupper(p2);
p2 = skip_string(p2,1);
p += 4;
@@ -1752,21 +1756,22 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
p2 = skip_string(p2,1);
p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
strcpy(p2,lp_workgroup());
+ strupper(p2);
p2 = skip_string(p2,1);
p += 4;
- SCVAL(p,0,MAJOR_VERSION);
- SCVAL(p,1,MINOR_VERSION);
+ SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
+ SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,lp_workgroup()); /* login domain?? */
+ strcpy(p2,lp_workgroup()); /* don't know. login domain?? */
p2 = skip_string(p2,1);
p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
strcpy(p2,"");
p2 = skip_string(p2,1);
p += 4;
@@ -1778,166 +1783,338 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
return(True);
}
-
/****************************************************************************
get info about a user
+
+ struct user_info_11 {
+ char usri11_name[21]; 0-20
+ char usri11_pad; 21
+ char *usri11_comment; 22-25
+ char *usri11_usr_comment; 26-29
+ unsigned short usri11_priv; 30-31
+ unsigned long usri11_auth_flags; 32-35
+ long usri11_password_age; 36-39
+ char *usri11_homedir; 40-43
+ char *usri11_parms; 44-47
+ long usri11_last_logon; 48-51
+ long usri11_last_logoff; 52-55
+ unsigned short usri11_bad_pw_count; 56-57
+ unsigned short usri11_num_logons; 58-59
+ char *usri11_logon_server; 60-63
+ unsigned short usri11_country_code; 64-65
+ char *usri11_workstations; 66-69
+ unsigned long usri11_max_storage; 70-73
+ unsigned short usri11_units_per_week; 74-75
+ unsigned char *usri11_logon_hours; 76-79
+ unsigned short usri11_code_page; 80-81
+ };
+
+where:
+
+ usri11_name specifies the user name for which information is retireved
+
+ usri11_pad aligns the next data structure element to a word boundary
+
+ usri11_comment is a null terminated ASCII comment
+
+ usri11_user_comment is a null terminated ASCII comment about the user
+
+ usri11_priv specifies the level of the privilege assigned to the user.
+ The possible values are:
+
+Name Value Description
+USER_PRIV_GUEST 0 Guest privilege
+USER_PRIV_USER 1 User privilege
+USER_PRV_ADMIN 2 Administrator privilege
+
+ usri11_auth_flags specifies the account operator privileges. The
+ possible values are:
+
+Name Value Description
+AF_OP_PRINT 0 Print operator
+
+
+Leach, Naik [Page 28]
+
+
+INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
+
+
+AF_OP_COMM 1 Communications operator
+AF_OP_SERVER 2 Server operator
+AF_OP_ACCOUNTS 3 Accounts operator
+
+
+ usri11_password_age specifies how many seconds have elapsed since the
+ password was last changed.
+
+ usri11_home_dir points to a null terminated ASCII string that contains
+ the path name of the user's home directory.
+
+ usri11_parms points to a null terminated ASCII string that is set
+ aside for use by applications.
+
+ usri11_last_logon specifies the time when the user last logged on.
+ This value is stored as the number of seconds elapsed since
+ 00:00:00, January 1, 1970.
+
+ usri11_last_logoff specifies the time when the user last logged off.
+ This value is stored as the number of seconds elapsed since
+ 00:00:00, January 1, 1970. A value of 0 means the last logoff
+ time is unknown.
+
+ usri11_bad_pw_count specifies the number of incorrect passwords
+ entered since the last successful logon.
+
+ usri11_log1_num_logons specifies the number of times this user has
+ logged on. A value of -1 means the number of logons is unknown.
+
+ usri11_logon_server points to a null terminated ASCII string that
+ contains the name of the server to which logon requests are sent.
+ A null string indicates logon requests should be sent to the
+ domain controller.
+
+ usri11_country_code specifies the country code for the user's language
+ of choice.
+
+ usri11_workstations points to a null terminated ASCII string that
+ contains the names of workstations the user may log on from.
+ There may be up to 8 workstations, with the names separated by
+ commas. A null strings indicates there are no restrictions.
+
+ usri11_max_storage specifies the maximum amount of disk space the user
+ can occupy. A value of 0xffffffff indicates there are no
+ restrictions.
+
+ usri11_units_per_week specifies the equal number of time units into
+ which a week is divided. This value must be equal to 168.
+
+ usri11_logon_hours points to a 21 byte (168 bits) string that
+ specifies the time during which the user can log on. Each bit
+ represents one unique hour in a week. The first bit (bit 0, word
+ 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
+
+
+
+Leach, Naik [Page 29]
+
+
+INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
+
+
+ Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
+ are no restrictions.
+
+ usri11_code_page specifies the code page for the user's language of
+ choice
+
+All of the pointers in this data structure need to be treated
+specially. The pointer is a 32 bit pointer. The higher 16 bits need
+to be ignored. The converter word returned in the parameters section
+needs to be subtracted from the lower 16 bits to calculate an offset
+into the return buffer where this ASCII string resides.
+
+There is no auxiliary data in the response.
+
****************************************************************************/
+#define usri11_name 0
+#define usri11_pad 21
+#define usri11_comment 22
+#define usri11_usr_comment 26
+#define usri11_full_name 30
+#define usri11_priv 34
+#define usri11_auth_flags 36
+#define usri11_password_age 40
+#define usri11_homedir 44
+#define usri11_parms 48
+#define usri11_last_logon 52
+#define usri11_last_logoff 56
+#define usri11_bad_pw_count 60
+#define usri11_num_logons 62
+#define usri11_logon_server 64
+#define usri11_country_code 68
+#define usri11_workstations 70
+#define usri11_max_storage 74
+#define usri11_units_per_week 78
+#define usri11_logon_hours 80
+#define usri11_code_page 84
+#define usri11_end 86
+
#define USER_PRIV_GUEST 0
#define USER_PRIV_USER 1
#define USER_PRIV_ADMIN 2
+#define AF_OP_PRINT 0
+#define AF_OP_COMM 1
+#define AF_OP_SERVER 2
+#define AF_OP_ACCOUNTS 3
+
static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *UserName = skip_string(str2,1);
- char *p = skip_string(UserName,1);
- int uLevel = SVAL(p,0);
- char *p2;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *UserName = skip_string(str2,1);
+ char *p = skip_string(UserName,1);
+ int uLevel = SVAL(p,0);
+ char *p2;
+
+ *rparam_len = 6;
+ *rparam = REALLOC(*rparam,*rparam_len);
+
+ /* check it's a supported varient */
+ if (strcmp(str1,"zWrLh") != 0) return False;
+ switch( uLevel )
+ {
+ case 0: p2 = "B21"; break;
+ case 1: p2 = "B21BB16DWzzWz"; break;
+ case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
+ case 10: p2 = "B21Bzzz"; break;
+ case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
+ default: return False;
+ }
- *rparam_len = 6;
- *rparam = REALLOC(*rparam,*rparam_len);
+ if (strcmp(p2,str2) != 0) return False;
- /* check it's a supported varient */
- if (strcmp(str1,"zWrLh") != 0) return False;
- switch( uLevel ) {
- case 0: p2 = "B21"; break;
- case 1: p2 = "B21BB16DWzzWz"; break;
- case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
- case 10: p2 = "B21Bzzz"; break;
- case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
- default: return False;
- }
- if (strcmp(p2,str2) != 0) return False;
+ *rdata_len = mdrcnt + 1024;
+ *rdata = REALLOC(*rdata,*rdata_len);
- *rdata_len = mdrcnt + 1024;
- *rdata = REALLOC(*rdata,*rdata_len);
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
+ p = *rdata;
+ p2 = p + usri11_end;
- p = *rdata;
- p2 = p + 86;
+ memset(p,0,21);
+ strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
- memset(p,0,21);
- strcpy(p,UserName);
- if (uLevel > 0) {
- SCVAL(p,21,0);
- *p2 = 0;
- if (uLevel >= 10) {
- SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
- strcpy(p2,"<Comment>");
- p2 = skip_string(p2,1);
- SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
- strcpy(p2,"<UserComment>");
- p2 = skip_string(p2,1);
- SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
- strcpy(p2,"<FullName>");
- p2 = skip_string(p2,1);
- }
- if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
- SSVAL(p,34,
- Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
- SIVAL(p,36,0); /* auth flags */
- SIVALS(p,40,-1); /* password age */
- SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
- if (*lp_logon_path())
- {
- strcpy(p2,lp_logon_path());
- }
- else
- {
- strcpy(p2,"\\\\%L\\HOMES");
- standard_sub_basic(p2);
- }
- p2 = skip_string(p2,1);
- SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
- SIVAL(p,52,0); /* last logon */
- SIVAL(p,56,0); /* last logoff */
- SSVALS(p,60,-1); /* bad pw counts */
- SSVALS(p,62,-1); /* num logons */
- SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
- strcpy(p2,"\\\\*");
- p2 = skip_string(p2,1);
- SSVAL(p,68,0); /* country code */
-
- SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
-
- SIVALS(p,74,-1); /* max storage */
- SSVAL(p,78,168); /* units per week */
- SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
- memset(p2,-1,21);
- SCVAL(p2,21,0); /* fix zero termination */
- p2 = skip_string(p2,1);
-
- SSVAL(p,84,0); /* code page */
- }
- if (uLevel == 1 || uLevel == 2) {
- memset(p+22,' ',16); /* password */
- SIVALS(p,38,-1); /* password age */
- 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
- {
- strcpy(p2,"\\\\%L\\HOMES");
- standard_sub_basic(p2);
- }
- p2 = skip_string(p2,1);
- SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
- *p2++ = 0;
- SSVAL(p,52,0); /* flags */
- SIVAL(p,54,0); /* script_path */
- if (uLevel == 2) {
- SIVAL(p,60,0); /* auth_flags */
- SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
- strcpy(p2,"<Full Name>");
- p2 = skip_string(p2,1);
- SIVAL(p,68,0); /* urs_comment */
- SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
- SIVAL(p,76,0); /* workstations */
- SIVAL(p,80,0); /* last_logon */
- SIVAL(p,84,0); /* last_logoff */
- SIVALS(p,88,-1); /* acct_expires */
- SIVALS(p,92,-1); /* max_storage */
- SSVAL(p,96,168); /* units_per_week */
- SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
- memset(p2,-1,21);
- p2 += 21;
- SSVALS(p,102,-1); /* bad_pw_count */
- SSVALS(p,104,-1); /* num_logons */
- SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
- strcpy(p2,"\\\\%L");
- standard_sub_basic(p2);
- p2 = skip_string(p2,1);
- SSVAL(p,110,49); /* country_code */
- SSVAL(p,112,860); /* code page */
- }
- }
- }
+ if (uLevel > 0)
+ {
+ SCVAL(p,usri11_pad,0); /* padding - 1 byte */
+ *p2 = 0;
+ }
+ if (uLevel >= 10)
+ {
+ SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
+ strcpy(p2,"Comment");
+ p2 = skip_string(p2,1);
+
+ SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
+ strcpy(p2,"UserComment");
+ p2 = skip_string(p2,1);
+
+ /* EEK! the cifsrap.txt doesn't have this in!!!! */
+ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
+#if 0
+ strcpy(p2,"FullName");
+#endif
+ strcpy(p2,UserName); /* suggest copying the user name, for now... */
+ p2 = skip_string(p2,1);
+ }
+ if (uLevel == 11) /* modelled after NTAS 3.51 reply */
+ {
+ SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+ 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
+ {
+ strcpy(p2,"\\\\%L\\%U");
+ }
+ standard_sub_basic(p2);
+ p2 = skip_string(p2,1);
+ SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+ SIVAL(p,usri11_last_logon,0); /* last logon */
+ SIVAL(p,usri11_last_logoff,0); /* last logoff */
+ SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
+ SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
+ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
+ strcpy(p2,"\\\\*");
+ p2 = skip_string(p2,1);
+ SSVAL(p,usri11_country_code,0); /* country code */
+
+ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+
+ SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
+ SSVAL(p,usri11_units_per_week,168); /* units per week */
+ SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
+
+ /* a simple way to get logon hours at all times. */
+ memset(p2,0xff,21);
+ SCVAL(p2,21,0); /* fix zero termination */
+ p2 = skip_string(p2,1);
+
+ SSVAL(p,usri11_code_page,0); /* code page */
+ }
+ if (uLevel == 1 || uLevel == 2)
+ {
+ memset(p+22,' ',16); /* password */
+ SIVALS(p,38,-1); /* password age */
+ 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
+ {
+ strcpy(p2,"\\\\%L\\%U");
+ }
+ standard_sub_basic(p2);
+ p2 = skip_string(p2,1);
+ SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
+ *p2++ = 0;
+ SSVAL(p,52,0); /* flags */
+ SIVAL(p,54,0); /* script_path */
+ if (uLevel == 2)
+ {
+ SIVAL(p,60,0); /* auth_flags */
+ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
+ strcpy(p2,"<Full Name>");
+ p2 = skip_string(p2,1);
+ SIVAL(p,68,0); /* urs_comment */
+ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+ SIVAL(p,76,0); /* workstations */
+ SIVAL(p,80,0); /* last_logon */
+ SIVAL(p,84,0); /* last_logoff */
+ SIVALS(p,88,-1); /* acct_expires */
+ SIVALS(p,92,-1); /* max_storage */
+ SSVAL(p,96,168); /* units_per_week */
+ SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
+ memset(p2,-1,21);
+ p2 += 21;
+ SSVALS(p,102,-1); /* bad_pw_count */
+ SSVALS(p,104,-1); /* num_logons */
+ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
+ strcpy(p2,"\\\\%L");
+ standard_sub_basic(p2);
+ p2 = skip_string(p2,1);
+ SSVAL(p,110,49); /* country_code */
+ SSVAL(p,112,860); /* code page */
+ }
+ }
- *rdata_len = PTR_DIFF(p2,*rdata);
+ *rdata_len = PTR_DIFF(p2,*rdata);
- SSVAL(*rparam,4,*rdata_len); /* is this right?? */
+ SSVAL(*rparam,4,*rdata_len); /* is this right?? */
- return(True);
+ return(True);
}
-
/*******************************************************************
get groups that a user is a member of
******************************************************************/
@@ -2016,9 +2193,8 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
desc.subformat = NULL;
desc.format = str2;
-
-
- if (init_package(&desc,1,0)) {
+ if (init_package(&desc,1,0))
+ {
PACKI(&desc,"W",0); /* code */
PACKS(&desc,"B21",name); /* eff. name */
PACKS(&desc,"B",""); /* pad */
@@ -2027,7 +2203,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
PACKI(&desc,"D",0); /* auth flags XXX */
PACKI(&desc,"W",0); /* num logons */
PACKI(&desc,"W",0); /* bad pw count */
- PACKI(&desc,"D",-1); /* last logon */
+ PACKI(&desc,"D",0); /* last logon */
PACKI(&desc,"D",-1); /* last logoff */
PACKI(&desc,"D",-1); /* logoff time */
PACKI(&desc,"D",-1); /* kickoff time */
@@ -2043,7 +2219,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
}
PACKS(&desc,"z",lp_workgroup());/* domain */
PACKS(&desc,"z",lp_logon_script()); /* script path */
- PACKI(&desc,"D",0); /* reserved */
+ PACKI(&desc,"D",0x00000000); /* reserved */
}
*rdata_len = desc.usedlen;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 1abcb8089f..57611553cc 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -2659,32 +2659,67 @@ int reply_lanman2(char *outbuf)
return (smb_len(outbuf)+4);
}
+
/****************************************************************************
reply for the nt protocol
****************************************************************************/
int reply_nt1(char *outbuf)
{
- int capabilities=0x300; /* has dual names + lock_and_read */
+ /* dual names + lock_and_read + nt SMBs + remote API calls */
+ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
+/*
+ other valid capabilities which we may support at some time...
+ CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
+ CAP_LARGE_FILES|CAP_LARGE_READX|
+ CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
+ */
+
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
+ int data_len;
+ int encrypt_len;
+ char challenge_len = 8;
+
+ if (lp_readraw() && lp_writeraw())
+ {
+ capabilities |= CAP_RAW_MODE;
+ }
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
- set_message(outbuf,17,doencrypt?8:0,True);
+ /* 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(lp_workgroup())+1);
+#else
+ data_len = encrypt_len + strlen(lp_workgroup()) + 1;
+#endif
+
+ set_message(outbuf,17,data_len,True);
+
+#if UNICODE
+ /* put the OEM'd domain name */
+ PutUniCode(smb_buf(outbuf)+encrypt_len,lp_workgroup());
+#else
+ strcpy(smb_buf(outbuf)+encrypt_len, lp_workgroup());
+#endif
+
CVAL(outbuf,smb_vwv1) = secword;
#ifdef SMB_PASSWD
/* Create a token value and add it to the outgoing packet. */
- if (doencrypt) {
+ if (doencrypt)
+ {
generate_next_challenge(smb_buf(outbuf));
+
/* Tell the nt machine how long the challenge is. */
- SSVALS(outbuf,smb_vwv16+1,8);
+ SSVALS(outbuf,smb_vwv16+1,challenge_len);
}
#endif
- SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
-
Protocol = PROTOCOL_NT1;
if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
@@ -2694,21 +2729,19 @@ int reply_nt1(char *outbuf)
#endif
}
- if (lp_readraw() && lp_writeraw())
- capabilities |= 1;
-
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
- SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
- SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
+ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
+ SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
+ SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
put_long_date(outbuf+smb_vwv11+1,t);
SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
+ SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
return (smb_len(outbuf)+4);
}
-
/* these are the protocol lists used for auto architecture detection:
WinNT 3.51: