00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 struct sam_database_info {
00030 uint32 index;
00031 uint32 serial_lo, serial_hi;
00032 uint32 date_lo, date_hi;
00033 };
00034
00035
00036
00037
00038
00039 static void send_repl_message(uint32 low_serial)
00040 {
00041 TDB_CONTEXT *tdb;
00042
00043 tdb = tdb_open_log(lock_path("connections.tdb"), 0,
00044 TDB_DEFAULT, O_RDONLY, 0);
00045
00046 if (!tdb) {
00047 DEBUG(3, ("send_repl_message(): failed to open connections "
00048 "database\n"));
00049 return;
00050 }
00051
00052 DEBUG(3, ("sending replication message, serial = 0x%04x\n",
00053 low_serial));
00054
00055 message_send_all(tdb, MSG_SMB_SAM_REPL, &low_serial,
00056 sizeof(low_serial), False, NULL);
00057
00058 tdb_close(tdb);
00059 }
00060
00061
00062
00063
00064
00065 void process_logon_packet(struct packet_struct *p, char *buf,int len,
00066 const char *mailslot)
00067 {
00068 struct dgram_packet *dgram = &p->packet.dgram;
00069 pstring my_name;
00070 fstring reply_name;
00071 pstring outbuf;
00072 int code;
00073 uint16 token = 0;
00074 uint32 ntversion = 0;
00075 uint16 lmnttoken = 0;
00076 uint16 lm20token = 0;
00077 uint32 domainsidsize;
00078 BOOL short_request = False;
00079 char *getdc;
00080 char *uniuser;
00081 pstring ascuser;
00082 char *unicomp;
00083
00084 memset(outbuf, 0, sizeof(outbuf));
00085
00086 if (!lp_domain_logons()) {
00087 DEBUG(5,("process_logon_packet: Logon packet received from IP %s and domain \
00088 logons are not enabled.\n", inet_ntoa(p->ip) ));
00089 return;
00090 }
00091
00092 pstrcpy(my_name, global_myname());
00093
00094 code = get_safe_SVAL(buf,len,buf,0,-1);
00095 DEBUG(4,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code));
00096
00097 switch (code) {
00098 case 0:
00099 {
00100 fstring mach_str, user_str, getdc_str;
00101 char *q = buf + 2;
00102 char *machine = q;
00103 char *user = skip_string(buf,len,machine);
00104
00105 if (!user || PTR_DIFF(user, buf) >= len) {
00106 DEBUG(0,("process_logon_packet: bad packet\n"));
00107 return;
00108 }
00109 getdc = skip_string(buf,len,user);
00110
00111 if (!getdc || PTR_DIFF(getdc, buf) >= len) {
00112 DEBUG(0,("process_logon_packet: bad packet\n"));
00113 return;
00114 }
00115 q = skip_string(buf,len,getdc);
00116
00117 if (!q || PTR_DIFF(q + 5, buf) > len) {
00118 DEBUG(0,("process_logon_packet: bad packet\n"));
00119 return;
00120 }
00121 token = SVAL(q,3);
00122
00123 fstrcpy(reply_name,my_name);
00124
00125 pull_ascii_fstring(mach_str, machine);
00126 pull_ascii_fstring(user_str, user);
00127 pull_ascii_fstring(getdc_str, getdc);
00128
00129 DEBUG(5,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n",
00130 mach_str,inet_ntoa(p->ip),user_str,token));
00131
00132 q = outbuf;
00133 SSVAL(q, 0, 6);
00134 q += 2;
00135
00136 fstrcpy(reply_name, "\\\\");
00137 fstrcat(reply_name, my_name);
00138 push_ascii(q,reply_name,
00139 sizeof(outbuf)-PTR_DIFF(q, outbuf),
00140 STR_TERMINATE);
00141 q = skip_string(outbuf,sizeof(outbuf),q);
00142
00143 SSVAL(q, 0, token);
00144 q += 2;
00145
00146 dump_data(4, outbuf, PTR_DIFF(q, outbuf));
00147
00148 send_mailslot(True, getdc_str,
00149 outbuf,PTR_DIFF(q,outbuf),
00150 global_myname(), 0x0,
00151 mach_str,
00152 dgram->source_name.name_type,
00153 p->ip, *iface_ip(p->ip), p->port);
00154 break;
00155 }
00156
00157 case QUERYFORPDC:
00158 {
00159 fstring mach_str, getdc_str;
00160 fstring source_name;
00161 char *q = buf + 2;
00162 char *machine = q;
00163
00164 if (!lp_domain_master()) {
00165
00166 return;
00167 }
00168
00169 getdc = skip_string(buf,len,machine);
00170
00171 if (!getdc || PTR_DIFF(getdc, buf) >= len) {
00172 DEBUG(0,("process_logon_packet: bad packet\n"));
00173 return;
00174 }
00175 q = skip_string(buf,len,getdc);
00176
00177 if (!q || PTR_DIFF(q, buf) >= len) {
00178 DEBUG(0,("process_logon_packet: bad packet\n"));
00179 return;
00180 }
00181 q = ALIGN2(q, buf);
00182
00183
00184
00185
00186
00187
00188
00189 if (len - PTR_DIFF(q, buf) <= 3) {
00190 short_request = True;
00191 } else {
00192 unicomp = q;
00193
00194 if (PTR_DIFF(q, buf) >= len) {
00195 DEBUG(0,("process_logon_packet: bad packet\n"));
00196 return;
00197 }
00198
00199
00200 q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp));
00201
00202 if (PTR_DIFF(q, buf) >= len) {
00203 DEBUG(0,("process_logon_packet: bad packet\n"));
00204 return;
00205 }
00206
00207 if (len - PTR_DIFF(q, buf) > 8) {
00208
00209
00210
00211
00212 int dom_len = CVAL(q, 0);
00213 q++;
00214 if (dom_len != 0) {
00215 q += dom_len + 1;
00216 }
00217 q += 16;
00218 }
00219
00220 if (PTR_DIFF(q + 8, buf) > len) {
00221 DEBUG(0,("process_logon_packet: bad packet\n"));
00222 return;
00223 }
00224
00225 ntversion = IVAL(q, 0);
00226 lmnttoken = SVAL(q, 4);
00227 lm20token = SVAL(q, 6);
00228 }
00229
00230
00231 q = outbuf;
00232 SSVAL(q, 0, QUERYFORPDC_R);
00233 q += 2;
00234
00235 fstrcpy(reply_name,my_name);
00236 push_ascii(q, reply_name,
00237 sizeof(outbuf)-PTR_DIFF(q, outbuf),
00238 STR_TERMINATE);
00239 q = skip_string(outbuf,sizeof(outbuf),q);
00240
00241
00242 if (!short_request) {
00243
00244 q = ALIGN2(q, outbuf);
00245
00246 q += dos_PutUniCode(q, my_name,
00247 sizeof(outbuf) - PTR_DIFF(q, outbuf),
00248 True);
00249 q += dos_PutUniCode(q, lp_workgroup(),
00250 sizeof(outbuf) - PTR_DIFF(q, outbuf),
00251 True);
00252 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) {
00253 return;
00254 }
00255 SIVAL(q, 0, 1);
00256 SSVAL(q, 4, 0xffff);
00257 SSVAL(q, 6, 0xffff);
00258 q += 8;
00259 }
00260
00261
00262
00263 pull_ascii_fstring(mach_str, machine);
00264
00265 DEBUG(5,("process_logon_packet: GETDC request from %s at IP %s, \
00266 reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
00267 mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(),
00268 QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken,
00269 (uint32)lm20token ));
00270
00271 dump_data(4, outbuf, PTR_DIFF(q, outbuf));
00272
00273 pull_ascii_fstring(getdc_str, getdc);
00274 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
00275
00276 send_mailslot(True, getdc_str,
00277 outbuf,PTR_DIFF(q,outbuf),
00278 global_myname(), 0x0,
00279 source_name,
00280 dgram->source_name.name_type,
00281 p->ip, *iface_ip(p->ip), p->port);
00282 return;
00283 }
00284
00285 case SAMLOGON:
00286
00287 {
00288 fstring getdc_str;
00289 fstring source_name;
00290 char *q = buf + 2;
00291 fstring asccomp;
00292
00293 q += 2;
00294
00295 if (PTR_DIFF(q, buf) >= len) {
00296 DEBUG(0,("process_logon_packet: bad packet\n"));
00297 return;
00298 }
00299
00300 unicomp = q;
00301 uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp));
00302
00303 if (PTR_DIFF(uniuser, buf) >= len) {
00304 DEBUG(0,("process_logon_packet: bad packet\n"));
00305 return;
00306 }
00307
00308 getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser));
00309
00310 if (PTR_DIFF(getdc, buf) >= len) {
00311 DEBUG(0,("process_logon_packet: bad packet\n"));
00312 return;
00313 }
00314
00315 q = skip_string(buf,len,getdc);
00316
00317 if (!q || PTR_DIFF(q + 8, buf) >= len) {
00318 DEBUG(0,("process_logon_packet: bad packet\n"));
00319 return;
00320 }
00321
00322 q += 4;
00323 domainsidsize = IVAL(q, 0);
00324 q += 4;
00325
00326 DEBUG(5,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len));
00327
00328 if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) {
00329 q += domainsidsize;
00330 q = ALIGN4(q, buf);
00331 }
00332
00333 DEBUG(5,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) ));
00334
00335 if (len - PTR_DIFF(q, buf) > 8) {
00336
00337
00338
00339
00340 int dom_len = CVAL(q, 0);
00341 q++;
00342 if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) {
00343 q += dom_len + 1;
00344 }
00345 q += 16;
00346 }
00347
00348 if (PTR_DIFF(q + 8, buf) > len) {
00349 DEBUG(0,("process_logon_packet: bad packet\n"));
00350 return;
00351 }
00352
00353 ntversion = IVAL(q, 0);
00354 lmnttoken = SVAL(q, 4);
00355 lm20token = SVAL(q, 6);
00356 q += 8;
00357
00358 DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
00359
00360
00361
00362
00363
00364
00365 pull_ucs2_pstring(ascuser, uniuser);
00366 pull_ucs2_fstring(asccomp, unicomp);
00367 DEBUG(5,("process_logon_packet: SAMLOGON user %s\n", ascuser));
00368
00369 fstrcpy(reply_name, "\\\\");
00370 fstrcat(reply_name, my_name);
00371
00372 DEBUG(5,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
00373 asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(),
00374 SAMLOGON_R ,lmnttoken));
00375
00376
00377
00378 q = outbuf;
00379
00380
00381 if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) {
00382 if (SVAL(uniuser, 0) == 0) {
00383 SSVAL(q, 0, SAMLOGON_UNK_R);
00384 } else {
00385 SSVAL(q, 0, SAMLOGON_R);
00386 }
00387
00388 q += 2;
00389
00390 q += dos_PutUniCode(q, reply_name,
00391 sizeof(outbuf) - PTR_DIFF(q, outbuf),
00392 True);
00393 q += dos_PutUniCode(q, ascuser,
00394 sizeof(outbuf) - PTR_DIFF(q, outbuf),
00395 True);
00396 q += dos_PutUniCode(q, lp_workgroup(),
00397 sizeof(outbuf) - PTR_DIFF(q, outbuf),
00398 True);
00399 }
00400 #ifdef HAVE_ADS
00401 else {
00402 struct GUID domain_guid;
00403 UUID_FLAT flat_guid;
00404 pstring domain;
00405 pstring hostname;
00406 char *component, *dc, *q1;
00407 uint8 size;
00408 char *q_orig = q;
00409 int str_offset;
00410
00411 get_mydnsdomname(domain);
00412 get_myname(hostname);
00413
00414 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) {
00415 return;
00416 }
00417 if (SVAL(uniuser, 0) == 0) {
00418 SIVAL(q, 0, SAMLOGON_AD_UNK_R);
00419 } else {
00420 SIVAL(q, 0, SAMLOGON_AD_R);
00421 }
00422 q += 4;
00423
00424 SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS|
00425 ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE);
00426 q += 4;
00427
00428
00429 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < UUID_FLAT_SIZE) {
00430 return;
00431 }
00432 if (False == secrets_fetch_domain_guid(domain, &domain_guid)) {
00433 DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain));
00434 return;
00435 }
00436
00437 smb_uuid_pack(domain_guid, &flat_guid);
00438 memcpy(q, &flat_guid.info, UUID_FLAT_SIZE);
00439 q += UUID_FLAT_SIZE;
00440
00441
00442 str_offset = q - q_orig;
00443 dc = domain;
00444 q1 = q;
00445 while ((component = strtok(dc, "."))) {
00446 dc = NULL;
00447 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) {
00448 return;
00449 }
00450 size = push_ascii(&q[1], component,
00451 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00452 0);
00453 if (size == (uint8)-1) {
00454 return;
00455 }
00456 SCVAL(q, 0, size);
00457 q += (size + 1);
00458 }
00459
00460
00461 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) {
00462 return;
00463 }
00464 SCVAL(q, 0, 0);
00465 q++;
00466
00467
00468 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
00469 SCVAL(q, 1, str_offset & 0xFF);
00470 q += 2;
00471
00472
00473 size = push_ascii(&q[1], hostname,
00474 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00475 0);
00476 if (size == (uint8)-1) {
00477 return;
00478 }
00479 SCVAL(q, 0, size);
00480 q += (size + 1);
00481
00482 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 3) {
00483 return;
00484 }
00485
00486 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
00487 SCVAL(q, 1, str_offset & 0xFF);
00488 q += 2;
00489
00490
00491 size = push_ascii(&q[1], lp_workgroup(),
00492 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00493 STR_UPPER);
00494 if (size == (uint8)-1) {
00495 return;
00496 }
00497 SCVAL(q, 0, size);
00498 q += (size + 1);
00499
00500
00501 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 2) {
00502 return;
00503 }
00504 SCVAL(q, 0, 0);
00505 q++;
00506
00507
00508 size = push_ascii(&q[1], my_name,
00509 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00510 0);
00511 if (size == (uint8)-1) {
00512 return;
00513 }
00514 SCVAL(q, 0, size);
00515 q += (size + 1);
00516
00517
00518 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) {
00519 return;
00520 }
00521 SCVAL(q, 0, 0);
00522 q++;
00523
00524
00525 if (SVAL(uniuser, 0) != 0) {
00526 size = push_ascii(&q[1], ascuser,
00527 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00528 0);
00529 if (size == (uint8)-1) {
00530 return;
00531 }
00532 SCVAL(q, 0, size);
00533 q += (size + 1);
00534 }
00535
00536 q_orig = q;
00537
00538 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) {
00539 return;
00540 }
00541 size = push_ascii(&q[1], "Default-First-Site-Name",
00542 sizeof(outbuf) - PTR_DIFF(q+1, outbuf),
00543 0);
00544 if (size == (uint8)-1) {
00545 return;
00546 }
00547 SCVAL(q, 0, size);
00548 q += (size + 1);
00549
00550 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 18) {
00551 return;
00552 }
00553
00554
00555 str_offset = q - q_orig;
00556 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F));
00557 SCVAL(q, 1, str_offset & 0xFF);
00558 q += 2;
00559
00560 SCVAL(q, 0, PTR_DIFF(q,q1));
00561 SCVAL(q, 1, 0x10);
00562
00563 SIVAL(q, 0, 0x00000002);
00564 q += 4;
00565 SIVAL(q, 0, (iface_ip(p->ip))->s_addr);
00566 q += 4;
00567 SIVAL(q, 0, 0x00000000);
00568 q += 4;
00569 SIVAL(q, 0, 0x00000000);
00570 q += 4;
00571 }
00572 #endif
00573
00574 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) {
00575 return;
00576 }
00577
00578
00579 SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13);
00580
00581 SSVAL(q, 4, 0xffff);
00582 SSVAL(q, 6, 0xffff);
00583 q += 8;
00584
00585 dump_data(4, outbuf, PTR_DIFF(q, outbuf));
00586
00587 pull_ascii_fstring(getdc_str, getdc);
00588 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
00589
00590 send_mailslot(True, getdc,
00591 outbuf,PTR_DIFF(q,outbuf),
00592 global_myname(), 0x0,
00593 source_name,
00594 dgram->source_name.name_type,
00595 p->ip, *iface_ip(p->ip), p->port);
00596 break;
00597 }
00598
00599
00600
00601
00602 case SAM_UAS_CHANGE:
00603 {
00604 struct sam_database_info *db_info;
00605 char *q = buf + 2;
00606 int i, db_count;
00607 uint32 low_serial;
00608
00609
00610
00611 if (PTR_DIFF(q + 16, buf) >= len) {
00612 DEBUG(0,("process_logon_packet: bad packet\n"));
00613 return;
00614 }
00615
00616 low_serial = IVAL(q, 0); q += 4;
00617
00618 q += 4;
00619 q += 4;
00620 q += 4;
00621
00622
00623
00624 q = skip_string(buf,len,q);
00625
00626 if (!q || PTR_DIFF(q, buf) >= len) {
00627 DEBUG(0,("process_logon_packet: bad packet\n"));
00628 return;
00629 }
00630
00631 q = skip_string(buf,len,q);
00632
00633 if (!q || PTR_DIFF(q, buf) >= len) {
00634 DEBUG(0,("process_logon_packet: bad packet\n"));
00635 return;
00636 }
00637
00638 q = skip_unibuf(q, PTR_DIFF(buf + len, q));
00639
00640 if (PTR_DIFF(q, buf) >= len) {
00641 DEBUG(0,("process_logon_packet: bad packet\n"));
00642 return;
00643 }
00644
00645 q = skip_unibuf(q, PTR_DIFF(buf + len, q));
00646
00647
00648
00649 if (PTR_DIFF(q + 2, buf) >= len) {
00650 DEBUG(0,("process_logon_packet: bad packet\n"));
00651 return;
00652 }
00653
00654 db_count = SVAL(q, 0); q += 2;
00655
00656 if (PTR_DIFF(q + (db_count*20), buf) >= len) {
00657 DEBUG(0,("process_logon_packet: bad packet\n"));
00658 return;
00659 }
00660
00661 db_info = SMB_MALLOC_ARRAY(struct sam_database_info, db_count);
00662
00663 if (db_info == NULL) {
00664 DEBUG(3, ("out of memory allocating info for %d databases\n", db_count));
00665 return;
00666 }
00667
00668 for (i = 0; i < db_count; i++) {
00669 db_info[i].index = IVAL(q, 0);
00670 db_info[i].serial_lo = IVAL(q, 4);
00671 db_info[i].serial_hi = IVAL(q, 8);
00672 db_info[i].date_lo = IVAL(q, 12);
00673 db_info[i].date_hi = IVAL(q, 16);
00674 q += 20;
00675 }
00676
00677
00678
00679 #if 0
00680
00681 q += IVAL(q, 0) + 4;
00682
00683 q += 2;
00684
00685
00686
00687 q += 4;
00688 q += 2;
00689 q += 2;
00690 #endif
00691
00692 SAFE_FREE(db_info);
00693
00694
00695
00696 send_repl_message(low_serial);
00697 break;
00698 }
00699
00700 default:
00701 DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code));
00702 return;
00703 }
00704 }