summaryrefslogtreecommitdiff
path: root/source3/libsmb/clidgram.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/clidgram.c')
-rw-r--r--source3/libsmb/clidgram.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 66c6ee1022..baee95b9aa 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -119,3 +119,168 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx,
MSG_SEND_PACKET,
(uint8 *)&p, sizeof(p)));
}
+
+static void mailslot_name(struct in_addr dc_ip, fstring name)
+{
+ fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr);
+}
+
+bool send_getdc_request(struct messaging_context *msg_ctx,
+ struct sockaddr_storage *dc_ss,
+ const char *domain_name,
+ const DOM_SID *sid)
+{
+ char outbuf[1024];
+ struct in_addr dc_ip;
+ char *p;
+ fstring my_acct_name;
+ fstring my_mailslot;
+ size_t sid_size;
+
+ if (dc_ss->ss_family != AF_INET) {
+ return false;
+ }
+
+ dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
+ mailslot_name(dc_ip, my_mailslot);
+
+ memset(outbuf, '\0', sizeof(outbuf));
+
+ p = outbuf;
+
+ SCVAL(p, 0, SAMLOGON);
+ p++;
+
+ SCVAL(p, 0, 0); /* Count pointer ... */
+ p++;
+
+ SIVAL(p, 0, 0); /* The sender's token ... */
+ p += 2;
+
+ p += dos_PutUniCode(p, global_myname(),
+ sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
+ fstr_sprintf(my_acct_name, "%s$", global_myname());
+ p += dos_PutUniCode(p, my_acct_name,
+ sizeof(outbuf) - PTR_DIFF(p, outbuf), True);
+
+ if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
+ return false;
+ }
+
+ memcpy(p, my_mailslot, strlen(my_mailslot)+1);
+ p += strlen(my_mailslot)+1;
+
+ if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) {
+ return false;
+ }
+
+ SIVAL(p, 0, 0x80);
+ p+=4;
+
+ sid_size = ndr_size_dom_sid(sid, 0);
+
+ SIVAL(p, 0, sid_size);
+ p+=4;
+
+ p = ALIGN4(p, outbuf);
+ if (PTR_DIFF(p, outbuf) > sizeof(outbuf)) {
+ return false;
+ }
+
+ if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
+ return false;
+ }
+ if (sid) {
+ sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
+ }
+
+ p += sid_size;
+
+ SIVAL(p, 0, 1);
+ SSVAL(p, 4, 0xffff);
+ SSVAL(p, 6, 0xffff);
+ p+=8;
+
+ return cli_send_mailslot(msg_ctx,
+ False, "\\MAILSLOT\\NET\\NTLOGON", 0,
+ outbuf, PTR_DIFF(p, outbuf),
+ global_myname(), 0, domain_name, 0x1c,
+ dc_ss);
+}
+
+bool receive_getdc_response(struct sockaddr_storage *dc_ss,
+ const char *domain_name,
+ fstring dc_name)
+{
+ struct packet_struct *packet;
+ fstring my_mailslot;
+ char *buf, *p;
+ fstring dcname, user, domain;
+ int len;
+ struct in_addr dc_ip;
+
+ if (dc_ss->ss_family != AF_INET) {
+ return false;
+ }
+ dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
+ mailslot_name(dc_ip, my_mailslot);
+
+ packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
+
+ if (packet == NULL) {
+ DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
+ return False;
+ }
+
+ DEBUG(5, ("Received packet for %s\n", my_mailslot));
+
+ buf = packet->packet.dgram.data;
+ len = packet->packet.dgram.datasize;
+
+ if (len < 70) {
+ /* 70 is a completely arbitrary value to make sure
+ the SVAL below does not read uninitialized memory */
+ DEBUG(3, ("GetDC got short response\n"));
+ return False;
+ }
+
+ /* This should be (buf-4)+SVAL(buf-4, smb_vwv12)... */
+ p = buf+SVAL(buf, smb_vwv10);
+
+ switch (CVAL(p, 0)) {
+ case SAMLOGON_R:
+ case SAMLOGON_UNK_R:
+ p+=2;
+ pull_ucs2(buf, dcname, p, sizeof(dcname), PTR_DIFF(buf+len, p),
+ STR_TERMINATE|STR_NOALIGN);
+ p = skip_unibuf(p, PTR_DIFF(buf+len, p));
+ pull_ucs2(buf, user, p, sizeof(user), PTR_DIFF(buf+len, p),
+ STR_TERMINATE|STR_NOALIGN);
+ p = skip_unibuf(p, PTR_DIFF(buf+len, p));
+ pull_ucs2(buf, domain, p, sizeof(domain), PTR_DIFF(buf+len, p),
+ STR_TERMINATE|STR_NOALIGN);
+ p = skip_unibuf(p, PTR_DIFF(buf+len, p));
+
+ if (!strequal(domain, domain_name)) {
+ DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
+ domain_name, domain));
+ return False;
+ }
+ break;
+
+ default:
+ DEBUG(8, ("GetDC got invalid response type %d\n", CVAL(p, 0)));
+ return False;
+ }
+ p = dcname;
+ if (*p == '\\') p += 1;
+ if (*p == '\\') p += 1;
+
+ fstrcpy(dc_name, p);
+
+ DEBUG(10, ("GetDC gave name %s for domain %s\n",
+ dc_name, domain));
+
+ return True;
+}
+