Changeset 745 for trunk/server/source3/libsmb/clidgram.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/libsmb/clidgram.c
r596 r745 10 10 the Free Software Foundation; either version 3 of the License, or 11 11 (at your option) any later version. 12 12 13 13 This program is distributed in the hope that it will be useful, 14 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 21 21 22 22 #include "includes.h" 23 #include "libsmb/libsmb.h" 24 #include "../lib/util/tevent_ntstatus.h" 25 #include "libsmb/clidgram.h" 26 #include "libsmb/nmblib.h" 27 #include "messages.h" 23 28 24 29 /* … … 26 31 */ 27 32 28 static bool cli_send_mailslot(struct messaging_context *msg_ctx, 29 bool unique, const char *mailslot, 33 static bool cli_prep_mailslot(bool unique, const char *mailslot, 30 34 uint16 priority, 31 35 char *buf, int len, 32 36 const char *srcname, int src_type, 33 37 const char *dstname, int dest_type, 34 const struct sockaddr_storage *dest_ss) 35 { 36 struct packet_struct p; 37 struct dgram_packet *dgram = &p.packet.dgram; 38 const struct sockaddr_storage *dest_ss, 39 int dgm_id, 40 struct packet_struct *p) 41 { 42 struct dgram_packet *dgram = &p->packet.dgram; 38 43 char *ptr, *p2; 39 44 char tmp[4]; 40 pid_t nmbd_pid;41 45 char addr[INET6_ADDRSTRLEN]; 42 46 43 if ((nmbd_pid = pidfile_pid("nmbd")) == 0) { 44 DEBUG(3, ("No nmbd found\n")); 45 return False; 46 } 47 48 if (dest_ss->ss_family != AF_INET) { 49 DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n")); 50 return false; 51 } 52 53 memset((char *)&p, '\0', sizeof(p)); 47 ZERO_STRUCTP(p); 54 48 55 49 /* … … 62 56 dgram->header.flags.first = True; 63 57 dgram->header.flags.more = False; 64 dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + 65 ((unsigned)sys_getpid()%(unsigned)100); 58 dgram->header.dgm_id = dgm_id; 66 59 /* source ip is filled by nmbd */ 67 60 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ … … 105 98 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ 106 99 107 p .packet_type = DGRAM_PACKET;108 p .ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;109 p .timestamp = time(NULL);100 p->packet_type = DGRAM_PACKET; 101 p->ip = ((const struct sockaddr_in *)dest_ss)->sin_addr; 102 p->timestamp = time(NULL); 110 103 111 104 DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ", … … 115 108 DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr)); 116 109 117 return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx, 118 pid_to_procid(nmbd_pid), 119 MSG_SEND_PACKET, 120 (uint8 *)&p, sizeof(p))); 121 } 122 123 static const char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip) 110 return true; 111 } 112 113 static char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip) 124 114 { 125 115 return talloc_asprintf(mem_ctx, "%s%X", … … 127 117 } 128 118 129 bool send_getdc_request(TALLOC_CTX *mem_ctx,130 struct messaging_context *msg_ctx,131 struct sockaddr_storage *dc_ss,132 const char *domain_name,133 const DOM_SID *sid,134 uint32_t nt_version)135 { 136 struct in_addr dc_ip; 137 const char *my_acct_name = NULL;138 const char *my_ mailslot = NULL;119 static bool prep_getdc_request(const struct sockaddr_storage *dc_ss, 120 const char *domain_name, 121 const struct dom_sid *sid, 122 uint32_t nt_version, 123 const char *my_mailslot, 124 int dgm_id, 125 struct packet_struct *p) 126 { 127 TALLOC_CTX *frame = talloc_stackframe(); 128 const char *my_acct_name; 139 129 struct nbt_netlogon_packet packet; 140 130 struct NETLOGON_SAM_LOGON_REQUEST *s; 141 131 enum ndr_err_code ndr_err; 142 DATA_BLOB blob ;132 DATA_BLOB blob = data_blob_null; 143 133 struct dom_sid my_sid; 134 bool ret = false; 144 135 145 136 ZERO_STRUCT(packet); 146 137 ZERO_STRUCT(my_sid); 147 138 148 if (dc_ss->ss_family != AF_INET) { 149 return false; 150 } 151 152 if (sid) { 139 if (sid != NULL) { 153 140 my_sid = *sid; 154 141 } 155 142 156 dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr; 157 my_mailslot = mailslot_name(mem_ctx, dc_ip); 158 if (!my_mailslot) { 159 return false; 160 } 161 162 my_acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 163 if (!my_acct_name) { 164 return false; 143 my_acct_name = talloc_asprintf(talloc_tos(), "%s$", global_myname()); 144 if (my_acct_name == NULL) { 145 goto fail; 165 146 } 166 147 … … 182 163 } 183 164 184 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet,165 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &packet, 185 166 (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_packet); 186 167 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 187 return false;188 } 189 190 ret urn cli_send_mailslot(msg_ctx,191 false, NBT_MAILSLOT_NTLOGON, 0,192 (char *)blob.data, blob.length,193 global_myname(), 0, domain_name, 0x1c,194 dc_ss); 195 } 196 197 bool receive_getdc_response(TALLOC_CTX *mem_ctx, 198 struct sockaddr_storage *dc_ss, 199 const char *domain_name, 200 uint32_t *nt_version,201 const char **dc_name,202 struct netlogon_samlogon_response **_r)203 { 204 struct packet_struct *packet;205 const char *my_mailslot = NULL;206 struct in_addr dc_ip; 168 goto fail; 169 } 170 171 ret = cli_prep_mailslot(false, NBT_MAILSLOT_NTLOGON, 0, 172 (char *)blob.data, blob.length, 173 global_myname(), 0, domain_name, 0x1c, 174 dc_ss, dgm_id, p); 175 fail: 176 TALLOC_FREE(frame); 177 return ret; 178 } 179 180 static bool parse_getdc_response( 181 struct packet_struct *packet, 182 TALLOC_CTX *mem_ctx, 183 const char *domain_name, 184 uint32_t *nt_version, 185 const char **dc_name, 186 struct netlogon_samlogon_response **samlogon_response) 187 { 207 188 DATA_BLOB blob; 208 struct netlogon_samlogon_response r;189 struct netlogon_samlogon_response *r; 209 190 union dgram_message_body p; 210 191 enum ndr_err_code ndr_err; … … 214 195 const char *returned_domain = NULL; 215 196 216 if (dc_ss->ss_family != AF_INET) {217 return false;218 }219 220 dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;221 222 my_mailslot = mailslot_name(mem_ctx, dc_ip);223 if (!my_mailslot) {224 return false;225 }226 227 packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);228 229 if (packet == NULL) {230 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));231 return False;232 }233 234 DEBUG(5, ("Received packet for %s\n", my_mailslot));235 236 197 blob = data_blob_const(packet->packet.dgram.data, 237 198 packet->packet.dgram.datasize); 238 239 199 if (blob.length < 4) { 240 DEBUG(0,("invalid length: %d\n", (int)blob.length)); 241 free_packet(packet); 200 DEBUG(1, ("invalid length: %d\n", (int)blob.length)); 242 201 return false; 243 202 } 244 203 245 204 if (RIVAL(blob.data,0) != DGRAM_SMB) { 246 DEBUG(0,("invalid packet\n")); 247 free_packet(packet); 205 DEBUG(1, ("invalid packet\n")); 248 206 return false; 249 207 } … … 252 210 blob.length -= 4; 253 211 254 ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, NULL,&p, DGRAM_SMB,212 ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB, 255 213 (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet); 256 214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 257 DEBUG(0,("failed to parse packet\n")); 258 free_packet(packet); 215 DEBUG(1, ("failed to parse packet\n")); 259 216 return false; 260 217 } 261 218 262 219 if (p.smb.smb_command != SMB_TRANSACTION) { 263 DEBUG(0,("invalid smb_command: %d\n", p.smb.smb_command)); 264 free_packet(packet); 220 DEBUG(1, ("invalid smb_command: %d\n", p.smb.smb_command)); 265 221 return false; 266 222 } … … 272 228 blob = p.smb.body.trans.data; 273 229 274 ZERO_STRUCT(r); 275 276 status = pull_netlogon_samlogon_response(&blob, mem_ctx, NULL, &r); 230 r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response); 231 if (!r) { 232 return false; 233 } 234 235 status = pull_netlogon_samlogon_response(&blob, r, r); 277 236 if (!NT_STATUS_IS_OK(status)) { 278 free_packet(packet);279 return false; 280 } 281 282 map_netlogon_samlogon_response( &r);237 TALLOC_FREE(r); 238 return false; 239 } 240 241 map_netlogon_samlogon_response(r); 283 242 284 243 /* do we still need this ? */ 285 *nt_version = r .ntver;286 287 returned_domain = r .data.nt5_ex.domain;288 returned_dc = r .data.nt5_ex.pdc_name;244 *nt_version = r->ntver; 245 246 returned_domain = r->data.nt5_ex.domain_name; 247 returned_dc = r->data.nt5_ex.pdc_name; 289 248 290 249 if (!strequal(returned_domain, domain_name)) { 291 250 DEBUG(3, ("GetDC: Expected domain %s, got %s\n", 292 251 domain_name, returned_domain)); 293 free_packet(packet); 294 return false; 295 } 252 TALLOC_FREE(r); 253 return false; 254 } 255 256 if (*returned_dc == '\\') returned_dc += 1; 257 if (*returned_dc == '\\') returned_dc += 1; 296 258 297 259 *dc_name = talloc_strdup(mem_ctx, returned_dc); 298 260 if (!*dc_name) { 299 free_packet(packet); 300 return false; 301 } 302 303 if (**dc_name == '\\') *dc_name += 1; 304 if (**dc_name == '\\') *dc_name += 1; 305 306 if (_r) { 307 *_r = (struct netlogon_samlogon_response *)talloc_memdup( 308 mem_ctx, &r, sizeof(struct netlogon_samlogon_response)); 309 if (!*_r) { 310 free_packet(packet); 311 return false; 312 } 261 TALLOC_FREE(r); 262 return false; 263 } 264 265 if (samlogon_response) { 266 *samlogon_response = r; 267 } else { 268 TALLOC_FREE(r); 313 269 } 314 270 … … 316 272 *dc_name, returned_domain)); 317 273 318 free_packet(packet);319 274 return True; 320 275 } 276 277 struct nbt_getdc_state { 278 struct tevent_context *ev; 279 struct messaging_context *msg_ctx; 280 struct nb_packet_reader *reader; 281 const char *my_mailslot; 282 pid_t nmbd_pid; 283 284 const struct sockaddr_storage *dc_addr; 285 const char *domain_name; 286 const struct dom_sid *sid; 287 uint32_t nt_version; 288 const char *dc_name; 289 struct netlogon_samlogon_response *samlogon_response; 290 291 struct packet_struct p; 292 }; 293 294 static void nbt_getdc_got_reader(struct tevent_req *subreq); 295 static void nbt_getdc_got_response(struct tevent_req *subreq); 296 297 struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx, 298 struct tevent_context *ev, 299 struct messaging_context *msg_ctx, 300 const struct sockaddr_storage *dc_addr, 301 const char *domain_name, 302 const struct dom_sid *sid, 303 uint32_t nt_version) 304 { 305 struct tevent_req *req, *subreq; 306 struct nbt_getdc_state *state; 307 uint16_t dgm_id; 308 309 req = tevent_req_create(mem_ctx, &state, struct nbt_getdc_state); 310 if (req == NULL) { 311 return NULL; 312 } 313 state->ev = ev; 314 state->msg_ctx = msg_ctx; 315 state->dc_addr = dc_addr; 316 state->domain_name = domain_name; 317 state->sid = sid; 318 state->nt_version = nt_version; 319 320 if (dc_addr->ss_family != AF_INET) { 321 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); 322 return tevent_req_post(req, ev); 323 } 324 state->my_mailslot = mailslot_name( 325 state, ((struct sockaddr_in *)dc_addr)->sin_addr); 326 if (tevent_req_nomem(state->my_mailslot, req)) { 327 return tevent_req_post(req, ev); 328 } 329 state->nmbd_pid = pidfile_pid("nmbd"); 330 if (state->nmbd_pid == 0) { 331 DEBUG(3, ("No nmbd found\n")); 332 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); 333 return tevent_req_post(req, ev); 334 } 335 336 generate_random_buffer((uint8_t *)(void *)&dgm_id, sizeof(dgm_id)); 337 338 if (!prep_getdc_request(dc_addr, domain_name, sid, nt_version, 339 state->my_mailslot, dgm_id & 0x7fff, 340 &state->p)) { 341 DEBUG(3, ("prep_getdc_request failed\n")); 342 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 343 return tevent_req_post(req, ev); 344 } 345 346 subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1, 347 state->my_mailslot); 348 if (tevent_req_nomem(subreq, req)) { 349 return tevent_req_post(req, ev); 350 } 351 tevent_req_set_callback(subreq, nbt_getdc_got_reader, req); 352 return req; 353 } 354 355 static void nbt_getdc_got_reader(struct tevent_req *subreq) 356 { 357 struct tevent_req *req = tevent_req_callback_data( 358 subreq, struct tevent_req); 359 struct nbt_getdc_state *state = tevent_req_data( 360 req, struct nbt_getdc_state); 361 NTSTATUS status; 362 363 status = nb_packet_reader_recv(subreq, state, &state->reader); 364 TALLOC_FREE(subreq); 365 if (tevent_req_nterror(req, status)) { 366 DEBUG(10, ("nb_packet_reader_recv returned %s\n", 367 nt_errstr(status))); 368 return; 369 } 370 371 status = messaging_send_buf( 372 state->msg_ctx, pid_to_procid(state->nmbd_pid), 373 MSG_SEND_PACKET, (uint8_t *)&state->p, sizeof(state->p)); 374 375 if (tevent_req_nterror(req, status)) { 376 DEBUG(10, ("messaging_send_buf returned %s\n", 377 nt_errstr(status))); 378 return; 379 } 380 subreq = nb_packet_read_send(state, state->ev, state->reader); 381 if (tevent_req_nomem(subreq, req)) { 382 return; 383 } 384 tevent_req_set_callback(subreq, nbt_getdc_got_response, req); 385 } 386 387 static void nbt_getdc_got_response(struct tevent_req *subreq) 388 { 389 struct tevent_req *req = tevent_req_callback_data( 390 subreq, struct tevent_req); 391 struct nbt_getdc_state *state = tevent_req_data( 392 req, struct nbt_getdc_state); 393 struct packet_struct *p; 394 NTSTATUS status; 395 bool ret; 396 397 status = nb_packet_read_recv(subreq, &p); 398 TALLOC_FREE(subreq); 399 if (tevent_req_nterror(req, status)) { 400 return; 401 } 402 403 ret = parse_getdc_response(p, state, state->domain_name, 404 &state->nt_version, &state->dc_name, 405 &state->samlogon_response); 406 free_packet(p); 407 if (!ret) { 408 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); 409 return; 410 } 411 tevent_req_done(req); 412 } 413 414 NTSTATUS nbt_getdc_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, 415 uint32_t *nt_version, const char **dc_name, 416 struct netlogon_samlogon_response **samlogon_response) 417 { 418 struct nbt_getdc_state *state = tevent_req_data( 419 req, struct nbt_getdc_state); 420 NTSTATUS status; 421 422 if (tevent_req_is_nterror(req, &status)) { 423 return status; 424 } 425 if (nt_version != NULL) { 426 *nt_version = state->nt_version; 427 } 428 if (dc_name != NULL) { 429 *dc_name = talloc_move(mem_ctx, &state->dc_name); 430 } 431 if (samlogon_response != NULL) { 432 *samlogon_response = talloc_move( 433 mem_ctx, &state->samlogon_response); 434 } 435 return NT_STATUS_OK; 436 } 437 438 NTSTATUS nbt_getdc(struct messaging_context *msg_ctx, 439 const struct sockaddr_storage *dc_addr, 440 const char *domain_name, 441 const struct dom_sid *sid, 442 uint32_t nt_version, 443 TALLOC_CTX *mem_ctx, 444 uint32_t *pnt_version, 445 const char **dc_name, 446 struct netlogon_samlogon_response **samlogon_response) 447 { 448 TALLOC_CTX *frame = talloc_stackframe(); 449 struct tevent_context *ev; 450 struct tevent_req *req; 451 NTSTATUS status = NT_STATUS_NO_MEMORY; 452 453 ev = tevent_context_init(frame); 454 if (ev == NULL) { 455 goto fail; 456 } 457 req = nbt_getdc_send(ev, ev, msg_ctx, dc_addr, domain_name, 458 sid, nt_version); 459 if (req == NULL) { 460 goto fail; 461 } 462 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 463 goto fail; 464 } 465 status = nbt_getdc_recv(req, mem_ctx, pnt_version, dc_name, 466 samlogon_response); 467 fail: 468 TALLOC_FREE(frame); 469 return status; 470 }
Note:
See TracChangeset
for help on using the changeset viewer.