diff options
author | Günther Deschner <gd@samba.org> | 2008-04-21 10:55:23 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2008-04-21 11:03:32 +0200 |
commit | 2d6a1c5da64195784b0b102edb268356a24d84b5 (patch) | |
tree | 24acafedc7f2156c9d41f947cfc5fa7f8f8b4f83 | |
parent | f27a20f25c9b2038621a6394821bbedbf17daa73 (diff) | |
download | samba-2d6a1c5da64195784b0b102edb268356a24d84b5.tar.gz |
winbind: Use libnbt for NTLOGON SAMLOGON mailslot request and reply.
Guenther
-rw-r--r-- | source/Makefile.in | 18 | ||||
-rw-r--r-- | source/libsmb/clidgram.c | 207 | ||||
-rw-r--r-- | source/winbindd/winbindd_cm.c | 4 |
3 files changed, 118 insertions, 111 deletions
diff --git a/source/Makefile.in b/source/Makefile.in index 09af6fcf5d6..27b562c3fab 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -285,15 +285,13 @@ LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_wkssvc.o \ librpc/gen_ndr/ndr_winreg.o \ librpc/gen_ndr/ndr_initshutdown.o \ librpc/gen_ndr/ndr_srvsvc.o \ - librpc/gen_ndr/ndr_svcctl.o \ librpc/gen_ndr/ndr_eventlog.o \ librpc/gen_ndr/ndr_netlogon.o \ librpc/gen_ndr/ndr_samr.o \ librpc/gen_ndr/ndr_dssetup.o \ librpc/gen_ndr/ndr_notify.o \ librpc/gen_ndr/ndr_xattr.o \ - librpc/gen_ndr/ndr_ntsvcs.o \ - librpc/gen_ndr/ndr_nbt.o + librpc/gen_ndr/ndr_ntsvcs.o RPC_PARSE_OBJ0 = rpc_parse/parse_prs.o rpc_parse/parse_misc.o @@ -403,9 +401,12 @@ LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o \ SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o +LIBNBT_OBJ = libcli/nbt/nbtname.o \ + librpc/gen_ndr/ndr_nbt.o \ + librpc/gen_ndr/ndr_svcctl.o + LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \ - libsmb/namequery.o libsmb/conncache.o libads/dns.o \ - libcli/nbt/nbtname.o + libsmb/namequery.o libsmb/conncache.o libads/dns.o NTERR_OBJ = libsmb/nterr.o DOSERR_OBJ = libsmb/doserr.o @@ -438,6 +439,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/smb_seal.o libsmb/async_smb.o \ $(LIBSAMBA_OBJ) \ $(LIBNMB_OBJ) \ + $(LIBNBT_OBJ) RPC_CLIENT_OBJ1 = rpc_client/cli_netlogon.o @@ -972,9 +974,9 @@ REPLACETORT_OBJ = lib/replace/test/testsuite.o \ $(LIBREPLACE_OBJ) NDRDUMP_OBJ = librpc/tools/ndrdump.o \ - $(PARAM_OBJ) $(LIBNDR_GEN_OBJ) \ - $(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - libcli/nbt/nbtname.o + $(PARAM_OBJ) $(LIBNDR_GEN_OBJ) \ + $(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ + librpc/gen_ndr/ndr_svcctl.o DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o diff --git a/source/libsmb/clidgram.c b/source/libsmb/clidgram.c index baee95b9aad..fed5fc0a143 100644 --- a/source/libsmb/clidgram.c +++ b/source/libsmb/clidgram.c @@ -120,9 +120,10 @@ bool cli_send_mailslot(struct messaging_context *msg_ctx, (uint8 *)&p, sizeof(p))); } -static void mailslot_name(struct in_addr dc_ip, fstring name) +static const char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip) { - fstr_sprintf(name, "\\MAILSLOT\\NET\\GETDC%X", dc_ip.s_addr); + return talloc_asprintf(mem_ctx, "%s%X", + NBT_MAILSLOT_GETDC, dc_ip.s_addr); } bool send_getdc_request(struct messaging_context *msg_ctx, @@ -130,100 +131,91 @@ bool send_getdc_request(struct messaging_context *msg_ctx, 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; + const char *my_acct_name = NULL; + const char *my_mailslot = NULL; + struct nbt_ntlogon_packet packet; + struct nbt_ntlogon_sam_logon *s; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + struct dom_sid my_sid; + TALLOC_CTX *mem_ctx = talloc_tos(); + + ZERO_STRUCT(packet); + ZERO_STRUCT(my_sid); 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 (sid) { + my_sid = *sid; + } - if (strlen(my_mailslot)+1 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; + my_mailslot = mailslot_name(mem_ctx, dc_ip); + if (!my_mailslot) { return false; } - memcpy(p, my_mailslot, strlen(my_mailslot)+1); - p += strlen(my_mailslot)+1; - - if (sizeof(outbuf) - PTR_DIFF(p, outbuf) < 8) { + my_acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); + if (!my_acct_name) { 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; + packet.command = NTLOGON_SAM_LOGON; + s = &packet.req.logon; + + s->request_count = 0; + s->computer_name = global_myname(); + s->user_name = my_acct_name; + s->mailslot_name = my_mailslot; + s->acct_control = ACB_WSTRUST; + s->sid = my_sid; + s->nt_version = 1; + s->lmnt_token = 0xffff; + s->lm20_token = 0xffff; + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(nbt_ntlogon_packet, &packet); } - if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) { + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &packet, + (ndr_push_flags_fn_t)ndr_push_nbt_ntlogon_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 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), + false, NBT_MAILSLOT_NTLOGON, 0, + (char *)blob.data, blob.length, global_myname(), 0, domain_name, 0x1c, dc_ss); } bool receive_getdc_response(struct sockaddr_storage *dc_ss, const char *domain_name, - fstring dc_name) + const char **dc_name) { struct packet_struct *packet; - fstring my_mailslot; - char *buf, *p; - fstring dcname, user, domain; - int len; + const char *my_mailslot = NULL; struct in_addr dc_ip; + TALLOC_CTX *mem_ctx = talloc_tos(); + DATA_BLOB blob; + struct nbt_ntlogon_packet r; + union dgram_message_body p; + enum ndr_err_code ndr_err; if (dc_ss->ss_family != AF_INET) { return false; } + dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; - mailslot_name(dc_ip, my_mailslot); + + my_mailslot = mailslot_name(mem_ctx, dc_ip); + if (!my_mailslot) { + return false; + } packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot); @@ -234,52 +226,63 @@ bool receive_getdc_response(struct sockaddr_storage *dc_ss, DEBUG(5, ("Received packet for %s\n", my_mailslot)); - buf = packet->packet.dgram.data; - len = packet->packet.dgram.datasize; + blob = data_blob_const(packet->packet.dgram.data, + 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; + if (blob.length < 4) { + DEBUG(0,("invalid length: %d\n", (int)blob.length)); + 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; + if (RIVAL(blob.data,0) != DGRAM_SMB) { + DEBUG(0,("invalid packet\n")); + return false; + } + + blob.data += 4; + blob.length -= 4; + + ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB, + (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("failed to parse packet\n")); + return false; + } + + if (p.smb.smb_command != SMB_TRANSACTION) { + DEBUG(0,("invalid smb_command: %d\n", p.smb.smb_command)); + return false; + } + + blob = p.smb.body.trans.data; + + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, + (ndr_pull_flags_fn_t)ndr_pull_nbt_ntlogon_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("failed to parse packet\n")); + return false; + } + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(nbt_ntlogon_packet, &r); + } + + if (!strequal(r.req.reply.domain, domain_name)) { + DEBUG(3, ("GetDC: Expected domain %s, got %s\n", + domain_name, r.req.reply.domain)); + return false; + } + + *dc_name = talloc_strdup(mem_ctx, r.req.reply.server); + if (!*dc_name) { + return false; } - p = dcname; - if (*p == '\\') p += 1; - if (*p == '\\') p += 1; - fstrcpy(dc_name, p); + if (**dc_name == '\\') *dc_name += 1; + if (**dc_name == '\\') *dc_name += 1; DEBUG(10, ("GetDC gave name %s for domain %s\n", - dc_name, domain)); + *dc_name, r.req.reply.domain)); return True; } diff --git a/source/winbindd/winbindd_cm.c b/source/winbindd/winbindd_cm.c index 73f74ca8ec0..97b22599850 100644 --- a/source/winbindd/winbindd_cm.c +++ b/source/winbindd/winbindd_cm.c @@ -1093,10 +1093,12 @@ static bool dcip_to_name(const struct winbindd_domain *domain, if (send_getdc_request(winbind_messaging_context(), pss, domain->name, &domain->sid)) { + const char *dc_name = NULL; int i; smb_msleep(100); for (i=0; i<5; i++) { - if (receive_getdc_response(pss, domain->name, name)) { + if (receive_getdc_response(pss, domain->name, &dc_name)) { + fstrcpy(name, dc_name); namecache_store(name, 0x20, 1, &ip_list); return True; } |