static bool only_ipaddrs_in_list(const char **list) { bool only_ip = true; if (!list) { return true; } for (; *list ; list++) { /* factor out the special strings */ if (strequal(*list, "ALL") || strequal(*list, "FAIL") || strequal(*list, "EXCEPT")) { continue; } if (!is_ipaddress(*list)) { /* * If we failed, make sure that it was not because * the token was a network/netmask pair. Only * network/netmask pairs have a '/' in them. */ if ((strchr_m(*list, '/')) == NULL) { only_ip = false; DEBUG(3,("only_ipaddrs_in_list: list has " "non-ip address (%s)\n", *list)); break; } } } return only_ip; }
struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, struct user_auth_info *user_info) { struct cli_state *cli; pstring myname; NTSTATUS nt_status; get_myname(myname); nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", user_info->username, lp_workgroup(), user_info->password, strlen(user_info->password)); if (NT_STATUS_IS_OK(nt_status)) { return cli; } else if (is_ipaddress(server)) { /* windows 9* needs a correct NMB name for connections */ fstring remote_name; if (name_status_find("*", 0, 0, *server_ip, remote_name)) { cli = get_ipc_connect(remote_name, server_ip, user_info); if (cli) return cli; } } return NULL; }
BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost, struct in_addr *pdest_ip) { struct nmb_name calling, called; make_nmb_name(&calling, srchost, 0x0); /* * If the called name is an IP address * then use *SMBSERVER immediately. */ if(is_ipaddress(desthost)) make_nmb_name(&called, "*SMBSERVER", 0x20); else make_nmb_name(&called, desthost, 0x20); if (!cli_session_request(cli, &calling, &called)) { struct nmb_name smbservername; make_nmb_name(&smbservername , "*SMBSERVER", 0x20); /* * If the name wasn't *SMBSERVER then * try with *SMBSERVER if the first name fails. */ if (nmb_name_equal(&called, &smbservername)) { /* * The name used was *SMBSERVER, don't bother with another name. */ DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER with error %s.\n", desthost, cli_errstr(cli) )); return False; } /* * We need to close the connection here but can't call cli_shutdown as * will free an allocated cli struct. cli_close_connection was invented * for this purpose. JRA. Based on work by "Kim R. Pedersen" <*****@*****.**>. */ cli_close_connection(cli); if (!cli_initialise(cli) || !cli_connect(cli, desthost, pdest_ip) || !cli_session_request(cli, &calling, &smbservername)) { DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) )); return False; } } return True; }
/* push a ipv4address */ _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address) { uint32_t addr; if (!is_ipaddress(address)) { return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS, "Invalid IPv4 address: '%s'", address); } addr = inet_addr(address); NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr))); return NDR_ERR_SUCCESS; }
static bool test_BindingString(struct torture_context *tctx, const void *test_data) { const char *binding = test_data; struct dcerpc_binding *b, *b2; const char *s, *s2; struct epm_tower tower; TALLOC_CTX *mem_ctx = tctx; /* Parse */ torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(mem_ctx, binding, &b), "Error parsing binding string"); s = dcerpc_binding_string(mem_ctx, b); torture_assert(tctx, s != NULL, "Error converting binding back to string"); torture_assert_casestr_equal(tctx, binding, s, "Mismatch while comparing original and regenerated binding strings"); /* Generate protocol towers */ torture_assert_ntstatus_ok(tctx, dcerpc_binding_build_tower(mem_ctx, b, &tower), "Error generating protocol tower"); /* Convert back to binding and then back to string and compare */ torture_assert_ntstatus_ok(tctx, dcerpc_binding_from_tower(mem_ctx, &tower, &b2), "Error generating binding from tower for original binding"); /* Compare to a stripped down version of the binding string because * the protocol tower doesn't contain the extra option data */ b->options = NULL; b->flags = 0; s = dcerpc_binding_string(mem_ctx, b); torture_assert(tctx, s != NULL, "Error converting binding back to string for (stripped down)"); s2 = dcerpc_binding_string(mem_ctx, b2); torture_assert(tctx, s != NULL, "Error converting binding back to string"); if (is_ipaddress(b->host)) torture_assert_casestr_equal(tctx, s, s2, "Mismatch while comparing original and from protocol tower generated binding strings"); return true; }
static bool test_wbc_resolve_winsbyname(struct torture_context *tctx) { const char *name; char *ip; wbcErr ret; name = torture_setting_string(tctx, "host", NULL); ret = wbcResolveWinsByName(name, &ip); if (is_ipaddress(name)) { torture_assert_wbc_equal(tctx, ret, WBC_ERR_DOMAIN_NOT_FOUND, "wbcResolveWinsByName failed"); } else { torture_assert_wbc_ok(tctx, ret, "wbcResolveWinsByName failed"); } return true; }
static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_security, bool gssapi) { const char *hostname; struct gensec_krb5_state *gensec_krb5_state; NTSTATUS nt_status; hostname = gensec_get_target_hostname(gensec_security); if (!hostname) { DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); return NT_STATUS_INVALID_PARAMETER; } if (is_ipaddress(hostname)) { DEBUG(2, ("Cannot do krb5 to an IP address")); return NT_STATUS_INVALID_PARAMETER; } if (strcmp(hostname, "localhost") == 0) { DEBUG(2, ("krb5 to 'localhost' does not make sense")); return NT_STATUS_INVALID_PARAMETER; } nt_status = gensec_krb5_start(gensec_security, gssapi); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START; gensec_krb5_state->ap_req_options = AP_OPTS_USE_SUBKEY; if (gensec_krb5_state->gssapi) { /* The Fake GSSAPI modal emulates Samba3, which does not do mutual authentication */ if (gensec_setting_bool(gensec_security->settings, "gensec_fake_gssapi_krb5", "mutual", false)) { gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; } } else { /* The wrapping for KPASSWD (a user of the raw KRB5 API) should be mutually authenticated */ if (gensec_setting_bool(gensec_security->settings, "gensec_krb5", "mutual", true)) { gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; } } return NT_STATUS_OK; }
/* push a ipv6address */ _PUBLIC_ enum ndr_err_code ndr_push_ipv6address(struct ndr_push *ndr, int ndr_flags, const char *address) { #ifdef AF_INET6 uint8_t addr[IPV6_BYTES]; int ret; if (!is_ipaddress(address)) { return ndr_push_error(ndr, NDR_ERR_IPV6ADDRESS, "Invalid IPv6 address: '%s'", address); } ret = inet_pton(AF_INET6, address, addr); if (ret <= 0) { return NDR_ERR_IPV6ADDRESS; } NDR_CHECK(ndr_push_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES)); return NDR_ERR_SUCCESS; #else return NDR_ERR_IPV6ADDRESS; #endif }
/* return true if the char* contains ip addrs only. Used to avoid gethostbyaddr() calls */ static BOOL only_ipaddrs_in_list(const char* list) { BOOL only_ip = True; char *listcopy, *tok; listcopy = strdup(list); for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep)) { /* factor out the special strings */ if (!strcasecmp(tok, "ALL") || !strcasecmp(tok, "FAIL") || !strcasecmp(tok, "EXCEPT")) { continue; } if (!is_ipaddress(tok)) { /* * if we failed, make sure that it was not because the token * was a network\netmask pair. Only network\netmask pairs * have a '/' in them */ if (strchr(tok, '/') == NULL) { only_ip = False; DEBUG(3,("only_ipaddrs_in_list: list [%s] has non-ip address %s\n", list, tok)); break; } } } SAFE_FREE(listcopy); return only_ip; }
NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower *tower) { const enum epm_protocol *protseq = NULL; int num_protocols = -1, i; NTSTATUS status; /* Find transport */ for (i=0;i<ARRAY_SIZE(transports);i++) { if (transports[i].transport == binding->transport) { protseq = transports[i].protseq; num_protocols = transports[i].num_protocols; break; } } if (num_protocols == -1) { DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport)); return NT_STATUS_UNSUCCESSFUL; } tower->num_floors = 2 + num_protocols; tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors); /* Floor 0 */ tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID; tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object); tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2); /* Floor 1 */ tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID; tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &ndr_transfer_syntax); tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2); /* Floor 2 to num_protocols */ for (i = 0; i < num_protocols; i++) { tower->floors[2 + i].lhs.protocol = protseq[i]; tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0); ZERO_STRUCT(tower->floors[2 + i].rhs); dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], ""); } /* The 4th floor contains the endpoint */ if (num_protocols >= 2 && binding->endpoint) { status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint); if (NT_STATUS_IS_ERR(status)) { return status; } } /* The 5th contains the network address */ if (num_protocols >= 3 && binding->host) { if (is_ipaddress(binding->host)) { status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], binding->host); } else { /* note that we don't attempt to resolve the name here - when we get a hostname here we are in the client code, and want to put in a wildcard all-zeros IP for the server to fill in */ status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], "0.0.0.0"); } if (NT_STATUS_IS_ERR(status)) { return status; } } return NT_STATUS_OK; }
static SMBCSRV * SMBC_server_internal(TALLOC_CTX *ctx, SMBCCTX *context, bool connect_if_not_found, const char *server, const char *share, char **pp_workgroup, char **pp_username, char **pp_password, bool *in_cache) { SMBCSRV *srv=NULL; char *workgroup = NULL; struct cli_state *c; struct nmb_name called, calling; const char *server_n = server; struct sockaddr_storage ss; int tried_reverse = 0; int port_try_first; int port_try_next; int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0); uint32 fs_attrs = 0; const char *username_used; NTSTATUS status; char *newserver, *newshare; zero_sockaddr(&ss); ZERO_STRUCT(c); *in_cache = false; if (server[0] == 0) { errno = EPERM; return NULL; } /* Look for a cached connection */ srv = SMBC_find_server(ctx, context, server, share, pp_workgroup, pp_username, pp_password); /* * If we found a connection and we're only allowed one share per * server... */ if (srv && *share != '\0' && smbc_getOptionOneSharePerServer(context)) { /* * ... then if there's no current connection to the share, * connect to it. SMBC_find_server(), or rather the function * pointed to by context->get_cached_srv_fn which * was called by SMBC_find_server(), will have issued a tree * disconnect if the requested share is not the same as the * one that was already connected. */ /* * Use srv->cli->desthost and srv->cli->share instead of * server and share below to connect to the actual share, * i.e., a normal share or a referred share from * 'msdfs proxy' share. */ if (srv->cli->cnum == (uint16) -1) { /* Ensure we have accurate auth info */ SMBC_call_auth_fn(ctx, context, srv->cli->desthost, srv->cli->share, pp_workgroup, pp_username, pp_password); if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; cli_shutdown(srv->cli); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, srv); return NULL; } /* * We don't need to renegotiate encryption * here as the encryption context is not per * tid. */ status = cli_tcon_andx(srv->cli, srv->cli->share, "?????", *pp_password, strlen(*pp_password)+1); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); cli_shutdown(srv->cli); srv->cli = NULL; smbc_getFunctionRemoveCachedServer(context)(context, srv); srv = NULL; } /* Determine if this share supports case sensitivity */ if (is_ipc) { DEBUG(4, ("IPC$ so ignore case sensitivity\n")); } else if (!cli_get_fs_attr_info(c, &fs_attrs)) { DEBUG(4, ("Could not retrieve " "case sensitivity flag: %s.\n", cli_errstr(c))); /* * We can't determine the case sensitivity of * the share. We have no choice but to use the * user-specified case sensitivity setting. */ if (smbc_getOptionCaseSensitive(context)) { cli_set_case_sensitive(c, True); } else { cli_set_case_sensitive(c, False); } } else { DEBUG(4, ("Case sensitive: %s\n", (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? "True" : "False"))); cli_set_case_sensitive( c, (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? True : False)); } /* * Regenerate the dev value since it's based on both * server and share */ if (srv) { srv->dev = (dev_t)(str_checksum(srv->cli->desthost) ^ str_checksum(srv->cli->share)); } } } /* If we have a connection... */ if (srv) { /* ... then we're done here. Give 'em what they came for. */ *in_cache = true; goto done; } /* If we're not asked to connect when a connection doesn't exist... */ if (! connect_if_not_found) { /* ... then we're done here. */ return NULL; } if (!*pp_workgroup || !*pp_username || !*pp_password) { errno = ENOMEM; return NULL; } make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0); make_nmb_name(&called , server, 0x20); DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); again: zero_sockaddr(&ss); /* have to open a new connection */ if ((c = cli_initialise()) == NULL) { errno = ENOMEM; return NULL; } if (smbc_getOptionUseKerberos(context)) { c->use_kerberos = True; } if (smbc_getOptionFallbackAfterKerberos(context)) { c->fallback_after_kerberos = True; } if (smbc_getOptionUseCCache(context)) { c->use_ccache = True; } c->timeout = smbc_getTimeout(context); /* * Force use of port 139 for first try if share is $IPC, empty, or * null, so browse lists can work */ if (share == NULL || *share == '\0' || is_ipc) { port_try_first = 139; port_try_next = 445; } else { port_try_first = 445; port_try_next = 139; } c->port = port_try_first; status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { /* First connection attempt failed. Try alternate port. */ c->port = port_try_next; status = cli_connect(c, server_n, &ss); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); errno = ETIMEDOUT; return NULL; } } if (!cli_session_request(c, &calling, &called)) { cli_shutdown(c); if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; } else { /* Try one more time, but ensure we don't loop */ /* Only try this if server is an IP address ... */ if (is_ipaddress(server) && !tried_reverse) { fstring remote_name; struct sockaddr_storage rem_ss; if (!interpret_string_addr(&rem_ss, server, NI_NUMERICHOST)) { DEBUG(4, ("Could not convert IP address " "%s to struct sockaddr_storage\n", server)); errno = ETIMEDOUT; return NULL; } tried_reverse++; /* Yuck */ if (name_status_find("*", 0, 0, &rem_ss, remote_name)) { make_nmb_name(&called, remote_name, 0x20); goto again; } } } errno = ETIMEDOUT; return NULL; } DEBUG(4,(" session request ok\n")); status = cli_negprot(c); if (!NT_STATUS_IS_OK(status)) { cli_shutdown(c); errno = ETIMEDOUT; return NULL; } username_used = *pp_username; if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, strlen(*pp_password), *pp_password, strlen(*pp_password), *pp_workgroup))) { fprintf(stderr, "JerryLin: Libsmb_server.c->SMBC_server_internal: cli_session_setup fail with username=[%s], password=[%s]\n", username_used, *pp_password); /* Failed. Try an anonymous login, if allowed by flags. */ username_used = ""; if (smbc_getOptionNoAutoAnonymousLogin(context) || !NT_STATUS_IS_OK(cli_session_setup(c, username_used, *pp_password, 1, *pp_password, 0, *pp_workgroup))) { cli_shutdown(c); errno = EPERM; return NULL; } } status = cli_init_creds(c, username_used, *pp_workgroup, *pp_password); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); cli_shutdown(c); return NULL; } DEBUG(4,(" session setup ok\n")); /* here's the fun part....to support 'msdfs proxy' shares (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL here before trying to connect to the original share. cli_check_msdfs_proxy() will fail if it is a normal share. */ if ((c->capabilities & CAP_DFS) && cli_check_msdfs_proxy(ctx, c, share, &newserver, &newshare, /* FIXME: cli_check_msdfs_proxy() does not support smbc_smb_encrypt_level type */ context->internal->smb_encryption_level ? true : false, *pp_username, *pp_password, *pp_workgroup)) { cli_shutdown(c); srv = SMBC_server_internal(ctx, context, connect_if_not_found, newserver, newshare, pp_workgroup, pp_username, pp_password, in_cache); TALLOC_FREE(newserver); TALLOC_FREE(newshare); return srv; } /* must be a normal share */ status = cli_tcon_andx(c, share, "?????", *pp_password, strlen(*pp_password)+1); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); fprintf(stderr, "JerryLin: Libsmb_server.c->SMBC_server_internal: cli_tcon_andx return %08X, errno=[%d]\n", NT_STATUS_V(status), errno); cli_shutdown(c); return NULL; } DEBUG(4,(" tconx ok\n")); /* Determine if this share supports case sensitivity */ if (is_ipc) { DEBUG(4, ("IPC$ so ignore case sensitivity\n")); } else if (!cli_get_fs_attr_info(c, &fs_attrs)) { DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n", cli_errstr(c))); /* * We can't determine the case sensitivity of the share. We * have no choice but to use the user-specified case * sensitivity setting. */ if (smbc_getOptionCaseSensitive(context)) { cli_set_case_sensitive(c, True); } else { cli_set_case_sensitive(c, False); } } else { DEBUG(4, ("Case sensitive: %s\n", (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? "True" : "False"))); cli_set_case_sensitive(c, (fs_attrs & FILE_CASE_SENSITIVE_SEARCH ? True : False)); } if (context->internal->smb_encryption_level) { /* Attempt UNIX smb encryption. */ if (!NT_STATUS_IS_OK(cli_force_encryption(c, username_used, *pp_password, *pp_workgroup))) { /* * context->smb_encryption_level == 1 * means don't fail if encryption can't be negotiated, * == 2 means fail if encryption can't be negotiated. */ DEBUG(4,(" SMB encrypt failed\n")); if (context->internal->smb_encryption_level == 2) { cli_shutdown(c); errno = EPERM; return NULL; } } DEBUG(4,(" SMB encrypt ok\n")); } /* * Ok, we have got a nice connection * Let's allocate a server structure. */ srv = SMB_MALLOC_P(SMBCSRV); if (!srv) { cli_shutdown(c); errno = ENOMEM; return NULL; } ZERO_STRUCTP(srv); srv->cli = c; srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); srv->no_pathinfo = False; srv->no_pathinfo2 = False; srv->no_nt_session = False; done: if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) { workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); } else { workgroup = *pp_workgroup; } if(!workgroup) { return NULL; } /* set the credentials to make DFS work */ smbc_set_credentials_with_fallback(context, workgroup, *pp_username, *pp_password); return srv; }
static WERROR ask_forwarder(struct dns_server *dns, TALLOC_CTX *mem_ctx, struct dns_name_question *question, struct dns_res_rec **answers, uint16_t *ancount, struct dns_res_rec **nsrecs, uint16_t *nscount, struct dns_res_rec **additional, uint16_t *arcount) { struct tevent_context *ev = tevent_context_init(mem_ctx); struct dns_name_packet *out_packet, *in_packet; uint16_t id = random(); DATA_BLOB out, in; enum ndr_err_code ndr_err; WERROR werr = WERR_OK; struct tevent_req *req; const char *forwarder = lpcfg_dns_forwarder(dns->task->lp_ctx); if (!is_ipaddress(forwarder)) { DEBUG(0, ("Invalid 'dns forwarder' setting '%s', needs to be " "an IP address\n", forwarder)); return DNS_ERR(NAME_ERROR); } out_packet = talloc_zero(mem_ctx, struct dns_name_packet); W_ERROR_HAVE_NO_MEMORY(out_packet); out_packet->id = id; out_packet->operation |= DNS_OPCODE_QUERY | DNS_FLAG_RECURSION_DESIRED; out_packet->qdcount = 1; out_packet->questions = question; ndr_err = ndr_push_struct_blob(&out, mem_ctx, out_packet, (ndr_push_flags_fn_t)ndr_push_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return DNS_ERR(SERVER_FAILURE); } req = dns_udp_request_send(mem_ctx, ev, forwarder, out.data, out.length); W_ERROR_HAVE_NO_MEMORY(req); if(!tevent_req_poll(req, ev)) { return DNS_ERR(SERVER_FAILURE); } werr = dns_udp_request_recv(req, mem_ctx, &in.data, &in.length); W_ERROR_NOT_OK_RETURN(werr); in_packet = talloc_zero(mem_ctx, struct dns_name_packet); W_ERROR_HAVE_NO_MEMORY(in_packet); ndr_err = ndr_pull_struct_blob(&in, in_packet, in_packet, (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return DNS_ERR(SERVER_FAILURE); } if (in_packet->id != id) { DEBUG(0, ("DNS packet id mismatch: 0x%0x, expected 0x%0x\n", in_packet->id, id)); return DNS_ERR(NAME_ERROR); } *ancount = in_packet->ancount; *answers = talloc_move(mem_ctx, &in_packet->answers); *nscount = in_packet->nscount; *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs); *arcount = in_packet->arcount; *additional = talloc_move(mem_ctx, &in_packet->additional); return werr; }
static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security) { struct gensec_gssapi_state *gensec_gssapi_state; struct cli_credentials *creds = gensec_get_credentials(gensec_security); NTSTATUS nt_status; gss_buffer_desc name_token; gss_OID name_type; OM_uint32 maj_stat, min_stat; const char *hostname = gensec_get_target_hostname(gensec_security); if (!hostname) { DEBUG(3, ("No hostname for target computer passed in, cannot use kerberos for this connection\n")); return NT_STATUS_INVALID_PARAMETER; } if (is_ipaddress(hostname)) { DEBUG(2, ("Cannot do GSSAPI to an IP address\n")); return NT_STATUS_INVALID_PARAMETER; } if (strcmp(hostname, "localhost") == 0) { DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n")); return NT_STATUS_INVALID_PARAMETER; } nt_status = gensec_gssapi_start(gensec_security); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state); if (cli_credentials_get_impersonate_principal(creds)) { gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); } gensec_gssapi_state->target_principal = gensec_get_target_principal(gensec_security); if (gensec_gssapi_state->target_principal) { name_type = GSS_C_NULL_OID; } else { gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%s@%s", gensec_get_target_service(gensec_security), hostname, cli_credentials_get_realm(creds)); name_type = GSS_C_NT_USER_NAME; } name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal); name_token.length = strlen(gensec_gssapi_state->target_principal); maj_stat = gss_import_name (&min_stat, &name_token, name_type, &gensec_gssapi_state->server_name); if (maj_stat) { DEBUG(2, ("GSS Import name of %s failed: %s\n", (char *)name_token.value, gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_INVALID_PARAMETER; } return NT_STATUS_OK; }
NTSTATUS cli_full_connection(struct cli_state **output_cli, const char *my_name, const char *dest_host, struct in_addr *dest_ip, int port, const char *service, const char *service_type, const char *user, const char *domain, const char *password, int pass_len) { struct ntuser_creds creds; NTSTATUS nt_status; struct nmb_name calling; struct nmb_name called; struct cli_state *cli; struct in_addr ip; if (!output_cli) DEBUG(0, ("output_cli is NULL!?!")); *output_cli = NULL; make_nmb_name(&calling, my_name, 0x0); make_nmb_name(&called , dest_host, 0x20); again: if (!(cli = cli_initialise(NULL))) return NT_STATUS_NO_MEMORY; if (cli_set_port(cli, port) != port) { cli_shutdown(cli); return NT_STATUS_UNSUCCESSFUL; } ip = *dest_ip; DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service)); if (!cli_connect(cli, dest_host, &ip)) { DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n", nmb_namestr(&called), inet_ntoa(*dest_ip))); cli_shutdown(cli); return NT_STATUS_UNSUCCESSFUL; } if (!cli_session_request(cli, &calling, &called)) { char *p; DEBUG(1,("session request to %s failed (%s)\n", called.name, cli_errstr(cli))); cli_shutdown(cli); if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) { *p = 0; goto again; } if (strcmp(called.name, "*SMBSERVER")) { make_nmb_name(&called , "*SMBSERVER", 0x20); goto again; } return NT_STATUS_UNSUCCESSFUL; } if (!cli_negprot(cli)) { DEBUG(1,("failed negprot\n")); nt_status = NT_STATUS_UNSUCCESSFUL; cli_shutdown(cli); return nt_status; } if (!cli_session_setup(cli, user, password, pass_len, password, pass_len, domain)) { DEBUG(1,("failed session setup\n")); nt_status = cli_nt_error(cli); cli_shutdown(cli); if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL; return nt_status; } if (service) { if (!cli_send_tconX(cli, service, service_type, password, pass_len)) { DEBUG(1,("failed tcon_X\n")); nt_status = cli_nt_error(cli); cli_shutdown(cli); if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL; return nt_status; } } init_creds(&creds, user, domain, password, pass_len); cli_init_creds(cli, &creds); *output_cli = cli; return NT_STATUS_OK; }
static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_security, bool gssapi) { struct gensec_krb5_state *gensec_krb5_state; krb5_error_code ret; NTSTATUS nt_status; struct ccache_container *ccache_container; const char *hostname; const char *principal; krb5_data in_data; hostname = gensec_get_target_hostname(gensec_security); if (!hostname) { DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); return NT_STATUS_INVALID_PARAMETER; } if (is_ipaddress(hostname)) { DEBUG(2, ("Cannot do krb5 to an IP address")); return NT_STATUS_INVALID_PARAMETER; } if (strcmp(hostname, "localhost") == 0) { DEBUG(2, ("krb5 to 'localhost' does not make sense")); return NT_STATUS_INVALID_PARAMETER; } nt_status = gensec_krb5_start(gensec_security, gssapi); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START; gensec_krb5_state->ap_req_options = AP_OPTS_USE_SUBKEY; if (gensec_krb5_state->gssapi) { /* The Fake GSSAPI modal emulates Samba3, which does not do mutual authentication */ if (gensec_setting_bool(gensec_security->settings, "gensec_fake_gssapi_krb5", "mutual", false)) { gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; } } else { /* The wrapping for KPASSWD (a user of the raw KRB5 API) should be mutually authenticated */ if (gensec_setting_bool(gensec_security->settings, "gensec_krb5", "mutual", true)) { gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; } } principal = gensec_get_target_principal(gensec_security); ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security), gensec_security->event_ctx, gensec_security->settings->lp_ctx, &ccache_container); switch (ret) { case 0: break; case KRB5KDC_ERR_PREAUTH_FAILED: return NT_STATUS_LOGON_FAILURE; case KRB5_KDC_UNREACH: DEBUG(3, ("Cannot reach a KDC we require to contact %s\n", principal)); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ default: DEBUG(1, ("gensec_krb5_start: Aquiring initiator credentials failed: %s\n", error_message(ret))); return NT_STATUS_UNSUCCESSFUL; } in_data.length = 0; if (principal && lp_client_use_spnego_principal(gensec_security->settings->lp_ctx)) { krb5_principal target_principal; ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal, &target_principal); if (ret == 0) { ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, gensec_krb5_state->ap_req_options, target_principal, &in_data, ccache_container->ccache, &gensec_krb5_state->enc_ticket); krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context, target_principal); } } else { ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, gensec_krb5_state->ap_req_options, gensec_get_target_service(gensec_security), hostname, &in_data, ccache_container->ccache, &gensec_krb5_state->enc_ticket); } switch (ret) { case 0: return NT_STATUS_OK; case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n", hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5_KDC_UNREACH: DEBUG(3, ("Cannot reach a KDC we require to contact host [%s]: %s\n", hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ case KRB5KDC_ERR_PREAUTH_FAILED: case KRB5KRB_AP_ERR_TKT_EXPIRED: case KRB5_CC_END: /* Too much clock skew - we will need to kinit to re-skew the clock */ case KRB5KRB_AP_ERR_SKEW: case KRB5_KDCREP_SKEW: { DEBUG(3, ("kerberos (mk_req) failed: %s\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); /*fall through*/ } /* just don't print a message for these really ordinary messages */ case KRB5_FCC_NOFILE: case KRB5_CC_NOTFOUND: case ENOENT: return NT_STATUS_UNSUCCESSFUL; break; default: DEBUG(0, ("kerberos: %s\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); return NT_STATUS_UNSUCCESSFUL; } }
static bool test_Map_tcpip(struct torture_context *tctx, struct dcerpc_binding_handle *h, struct ndr_syntax_id map_syntax) { struct epm_Map r; struct GUID uuid; struct policy_handle entry_handle; struct ndr_syntax_id syntax; struct dcerpc_binding map_binding; struct epm_twr_t map_tower; struct epm_twr_p_t towers[20]; struct epm_tower t; uint32_t num_towers; uint32_t port; uint32_t i; long int p; const char *tmp; const char *ip; char *ptr; NTSTATUS status; torture_comment(tctx, "Testing epm_Map\n"); ZERO_STRUCT(uuid); ZERO_STRUCT(entry_handle); r.in.object = &uuid; r.in.map_tower = &map_tower; r.in.entry_handle = &entry_handle; r.out.entry_handle = &entry_handle; r.in.max_towers = 10; r.out.towers = towers; r.out.num_towers = &num_towers; /* Create map tower */ map_binding.transport = NCACN_IP_TCP; map_binding.object = map_syntax; map_binding.host = "0.0.0.0"; map_binding.endpoint = "135"; status = dcerpc_binding_build_tower(tctx, &map_binding, &map_tower.tower); torture_assert_ntstatus_ok(tctx, status, "epm_Map_tcpip failed: can't create map_tower"); torture_comment(tctx, "epm_Map request for '%s':\n", ndr_interface_name(&map_syntax.uuid, map_syntax.if_version)); display_tower(tctx, &r.in.map_tower->tower); status = dcerpc_epm_Map_r(h, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "epm_Map_simple failed"); torture_assert(tctx, r.out.result == EPMAPPER_STATUS_OK, "epm_Map_tcpip failed: result is not EPMAPPER_STATUS_OK"); /* Check the result */ t = r.out.towers[0].twr->tower; /* Check if we got the correct RPC interface identifier */ dcerpc_floor_get_lhs_data(&t.floors[0], &syntax); torture_assert(tctx, ndr_syntax_id_equal(&syntax, &map_syntax), "epm_Map_tcpip failed: Interface identifier mismatch"); torture_comment(tctx, "epm_Map_tcpip response for '%s':\n", ndr_interface_name(&syntax.uuid, syntax.if_version)); dcerpc_floor_get_lhs_data(&t.floors[1], &syntax); torture_assert(tctx, ndr_syntax_id_equal(&syntax, &ndr_transfer_syntax_ndr), "epm_Map_tcpip failed: floor 2 is not NDR encoded"); torture_assert(tctx, t.floors[2].lhs.protocol == EPM_PROTOCOL_NCACN, "epm_Map_tcpip failed: floor 3 is not NCACN_IP_TCP"); tmp = dcerpc_floor_get_rhs_data(tctx, &t.floors[3]); p = strtol(tmp, &ptr, 10); port = p & 0xffff; torture_assert(tctx, port > 1024 && port < 65535, "epm_Map_tcpip failed"); ip = dcerpc_floor_get_rhs_data(tctx, &t.floors[4]); torture_assert(tctx, is_ipaddress(ip), "epm_Map_tcpip failed"); for (i = 0; i < *r.out.num_towers; i++) { if (r.out.towers[i].twr) { display_tower(tctx, &t); } } return true; }