krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int fd, int flags) { krb5_error_code ret; krb5_address local_k_address, remote_k_address; krb5_address *lptr = NULL, *rptr = NULL; struct sockaddr_storage ss_local, ss_remote; struct sockaddr *local = (struct sockaddr *)&ss_local; struct sockaddr *remote = (struct sockaddr *)&ss_remote; socklen_t len; if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) { if (auth_context->local_address == NULL) { len = sizeof(ss_local); if(getsockname(fd, local, &len) < 0) { ret = errno; krb5_set_error_message(context, ret, "getsockname: %s", strerror(ret)); goto out; } ret = krb5_sockaddr2address (context, local, &local_k_address); if(ret) goto out; if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) { krb5_sockaddr2port (context, local, &auth_context->local_port); } else auth_context->local_port = 0; lptr = &local_k_address; } } if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) { len = sizeof(ss_remote); if(getpeername(fd, remote, &len) < 0) { ret = errno; krb5_set_error_message(context, ret, "getpeername: %s", strerror(ret)); goto out; } ret = krb5_sockaddr2address (context, remote, &remote_k_address); if(ret) goto out; if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) { krb5_sockaddr2port (context, remote, &auth_context->remote_port); } else auth_context->remote_port = 0; rptr = &remote_k_address; } ret = krb5_auth_con_setaddrs (context, auth_context, lptr, rptr); out: if (lptr) krb5_free_address (context, lptr); if (rptr) krb5_free_address (context, rptr); return ret; }
static krb5_error_code set_address (krb5_context context, krb5_kdc_configuration *config, EncTicketPart *et, struct sockaddr *addr, const char *from) { krb5_error_code ret; krb5_address *v4_addr; v4_addr = malloc (sizeof(*v4_addr)); if (v4_addr == NULL) return ENOMEM; ret = krb5_sockaddr2address(context, addr, v4_addr); if(ret) { free (v4_addr); kdc_log(context, config, 0, "Failed to convert address (%s)", from); return ret; } if (et->caddr && !krb5_address_search (context, v4_addr, et->caddr)) { kdc_log(context, config, 0, "Incorrect network address (%s)", from); krb5_free_address(context, v4_addr); free (v4_addr); return KRB5KRB_AP_ERR_BADADDR; } if(v4_addr->addr_type == KRB5_ADDRESS_INET) { /* we need to collapse the addresses in the ticket to a single address; best guess is to use the address the connection came from */ if (et->caddr != NULL) { free_HostAddresses(et->caddr); } else { et->caddr = malloc (sizeof (*et->caddr)); if (et->caddr == NULL) { krb5_free_address(context, v4_addr); free(v4_addr); return ENOMEM; } } et->caddr->val = v4_addr; et->caddr->len = 1; } else { krb5_free_address(context, v4_addr); free(v4_addr); } return 0; }
static krb5_error_code add_addrs(krb5_context context, krb5_addresses *addr, struct addrinfo *ai) { krb5_error_code ret; unsigned n, i; void *tmp; struct addrinfo *a; n = 0; for (a = ai; a != NULL; a = a->ai_next) ++n; tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val)); if (tmp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto fail; } addr->val = tmp; for (i = addr->len; i < (addr->len + n); ++i) { addr->val[i].addr_type = 0; krb5_data_zero(&addr->val[i].address); } i = addr->len; for (a = ai; a != NULL; a = a->ai_next) { krb5_address ad; ret = krb5_sockaddr2address (context, a->ai_addr, &ad); if (ret == 0) { if (krb5_address_search(context, &ad, addr)) krb5_free_address(context, &ad); else addr->val[i++] = ad; } else if (ret == KRB5_PROG_ATYPE_NOSUPP) krb5_clear_error_string (context); else goto fail; addr->len = i; } return 0; fail: krb5_free_addresses (context, addr); return ret; }
static int spawn_child(krb5_context contextp, int *socks, unsigned int num_socks, int this_sock) { int e; size_t i; struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; socklen_t sa_size = sizeof(__ss); krb5_socket_t s; pid_t pid; krb5_address addr; char buf[128]; size_t buf_len; s = accept(socks[this_sock], sa, &sa_size); if(rk_IS_BAD_SOCKET(s)) { krb5_warn(contextp, rk_SOCK_ERRNO, "accept"); return 1; } e = krb5_sockaddr2address(contextp, sa, &addr); if(e) krb5_warn(contextp, e, "krb5_sockaddr2address"); else { e = krb5_print_address (&addr, buf, sizeof(buf), &buf_len); if(e) krb5_warn(contextp, e, "krb5_print_address"); else krb5_warnx(contextp, "connection from %s", buf); krb5_free_address(contextp, &addr); } pid = fork(); if(pid == 0) { for(i = 0; i < num_socks; i++) rk_closesocket(socks[i]); dup2(s, STDIN_FILENO); dup2(s, STDOUT_FILENO); if(s != STDIN_FILENO && s != STDOUT_FILENO) rk_closesocket(s); return 0; } else { rk_closesocket(s); } return 1; }
krb5_boolean _kdc_check_addresses(krb5_context context, krb5_kdc_configuration *config, HostAddresses *addresses, const struct sockaddr *from) { krb5_error_code ret; krb5_address addr; krb5_boolean result; krb5_boolean only_netbios = TRUE; size_t i; if(config->check_ticket_addresses == 0) return TRUE; if(addresses == NULL) return config->allow_null_ticket_addresses; for (i = 0; i < addresses->len; ++i) { if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) { only_netbios = FALSE; } } /* Windows sends it's netbios name, which I can only assume is * used for the 'allowed workstations' check. This is painful, * but we still want to check IP addresses if they happen to be * present. */ if(only_netbios) return config->allow_null_ticket_addresses; ret = krb5_sockaddr2address (context, from, &addr); if(ret) return FALSE; result = krb5_address_search(context, &addr, addresses); krb5_free_address (context, &addr); return result; }
krb5_error_code _gsskrb5i_address_to_krb5addr(krb5_context context, OM_uint32 gss_addr_type, gss_buffer_desc *gss_addr, int16_t port, krb5_address *address) { int addr_type; struct sockaddr sa; krb5_socklen_t sa_size = sizeof(sa); krb5_error_code problem; if (gss_addr == NULL) return GSS_S_FAILURE; switch (gss_addr_type) { #ifdef HAVE_IPV6 case GSS_C_AF_INET6: addr_type = AF_INET6; break; #endif /* HAVE_IPV6 */ case GSS_C_AF_INET: addr_type = AF_INET; break; default: return GSS_S_FAILURE; } problem = krb5_h_addr2sockaddr (context, addr_type, gss_addr->value, &sa, &sa_size, port); if (problem) return GSS_S_FAILURE; problem = krb5_sockaddr2address (context, &sa, address); return problem; }
static void write_stats(krb5_context context, slave *slaves, u_int32_t current_version) { char str[100]; rtbl_t tbl; time_t t = time(NULL); FILE *fp; fp = fopen(slave_stats_file, "w"); if (fp == NULL) return; krb5_format_time(context, t, str, sizeof(str), TRUE); fprintf(fp, "Status for slaves, last updated: %s\n\n", str); fprintf(fp, "Master version: %lu\n\n", (unsigned long)current_version); tbl = rtbl_create(); if (tbl == NULL) { fclose(fp); return; } rtbl_add_column(tbl, SLAVE_NAME, 0); rtbl_add_column(tbl, SLAVE_ADDRESS, 0); rtbl_add_column(tbl, SLAVE_VERSION, RTBL_ALIGN_RIGHT); rtbl_add_column(tbl, SLAVE_STATUS, 0); rtbl_add_column(tbl, SLAVE_SEEN, 0); rtbl_set_prefix(tbl, " "); rtbl_set_column_prefix(tbl, SLAVE_NAME, ""); while (slaves) { krb5_address addr; krb5_error_code ret; rtbl_add_column_entry(tbl, SLAVE_NAME, slaves->name); ret = krb5_sockaddr2address (context, (struct sockaddr*)&slaves->addr, &addr); if(ret == 0) { krb5_print_address(&addr, str, sizeof(str), NULL); krb5_free_address(context, &addr); rtbl_add_column_entry(tbl, SLAVE_ADDRESS, str); } else rtbl_add_column_entry(tbl, SLAVE_ADDRESS, "<unknown>"); snprintf(str, sizeof(str), "%u", (unsigned)slaves->version); rtbl_add_column_entry(tbl, SLAVE_VERSION, str); if (slaves->flags & SLAVE_F_DEAD) rtbl_add_column_entry(tbl, SLAVE_STATUS, "Down"); else rtbl_add_column_entry(tbl, SLAVE_STATUS, "Up"); ret = krb5_format_time(context, slaves->seen, str, sizeof(str), TRUE); rtbl_add_column_entry(tbl, SLAVE_SEEN, str); slaves = slaves->next; } rtbl_format(tbl, fp); rtbl_destroy(tbl); fclose(fp); }
int krb5_kdc_save_request(krb5_context context, const char *fn, const unsigned char *buf, size_t len, const krb5_data *reply, const struct sockaddr *sa) { krb5_storage *sp; krb5_address a; int fd, ret; uint32_t t; krb5_data d; memset(&a, 0, sizeof(a)); d.data = rk_UNCONST(buf); d.length = len; t = _kdc_now.tv_sec; fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); if (fd < 0) { int saved_errno = errno; krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn); return saved_errno; } sp = krb5_storage_from_fd(fd); close(fd); if (sp == NULL) { krb5_set_error_message(context, ENOMEM, "Storage failed to open fd"); return ENOMEM; } ret = krb5_sockaddr2address(context, sa, &a); if (ret) goto out; krb5_store_uint32(sp, 1); krb5_store_uint32(sp, t); krb5_store_address(sp, a); krb5_store_data(sp, d); { Der_class cl; Der_type ty; unsigned int tag; ret = der_get_tag (reply->data, reply->length, &cl, &ty, &tag, NULL); if (ret) { krb5_store_uint32(sp, 0xffffffff); krb5_store_uint32(sp, 0xffffffff); } else { krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0)); krb5_store_uint32(sp, tag); } } krb5_free_address(context, &a); out: krb5_storage_free(sp); return 0; }
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi) { krb5_error_code ret; struct gensec_krb5_state *gensec_krb5_state; struct cli_credentials *creds; const struct tsocket_address *tlocal_addr, *tremote_addr; krb5_address my_krb5_addr, peer_krb5_addr; creds = gensec_get_credentials(gensec_security); if (!creds) { return NT_STATUS_INVALID_PARAMETER; } gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state); if (!gensec_krb5_state) { return NT_STATUS_NO_MEMORY; } gensec_security->private_data = gensec_krb5_state; gensec_krb5_state->smb_krb5_context = NULL; gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ticket = NULL; ZERO_STRUCT(gensec_krb5_state->enc_ticket); gensec_krb5_state->keyblock = NULL; gensec_krb5_state->gssapi = gssapi; talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); if (cli_credentials_get_krb5_context(creds, gensec_security->settings->lp_ctx, &gensec_krb5_state->smb_krb5_context)) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } tlocal_addr = gensec_get_local_address(gensec_security); if (tlocal_addr) { ssize_t socklen; struct sockaddr_storage ss; socklen = tsocket_address_bsd_sockaddr(tlocal_addr, (struct sockaddr *) &ss, sizeof(struct sockaddr_storage)); if (socklen < 0) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, (const struct sockaddr *) &ss, &my_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } tremote_addr = gensec_get_remote_address(gensec_security); if (tremote_addr) { ssize_t socklen; struct sockaddr_storage ss; socklen = tsocket_address_bsd_sockaddr(tremote_addr, (struct sockaddr *) &ss, sizeof(struct sockaddr_storage)); if (socklen < 0) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, (const struct sockaddr *) &ss, &peer_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, tlocal_addr ? &my_krb5_addr : NULL, tremote_addr ? &peer_krb5_addr : NULL); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } return NT_STATUS_OK; }
static int doit (krb5_keytab keytab, int port) { krb5_error_code ret; int *sockets; int maxfd; krb5_realm *realms; krb5_addresses addrs; krb5_address *my_addrp; unsigned n, i; fd_set real_fdset; struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; #ifdef INETD_SUPPORT int fdz; int from_inetd; socklen_t fromlen; krb5_address my_addr; struct sockaddr_storage __local; struct sockaddr *localsa = (struct sockaddr *)&__local; #endif ret = krb5_get_default_realms(context, &realms); if (ret) krb5_err (context, 1, ret, "krb5_get_default_realms"); #ifdef INETD_SUPPORT fromlen = sizeof __ss; from_inetd = (getsockname(0, sa, &fromlen) == 0); if (!from_inetd) { #endif if (explicit_addresses.len) { addrs = explicit_addresses; } else { ret = krb5_get_all_server_addrs (context, &addrs); if (ret) krb5_err (context, 1, ret, "krb5_get_all_server_addrs"); } n = addrs.len; sockets = malloc (n * sizeof(*sockets)); if (sockets == NULL) krb5_errx (context, 1, "out of memory"); maxfd = -1; FD_ZERO(&real_fdset); for (i = 0; i < n; ++i) { krb5_socklen_t sa_size = sizeof(__ss); krb5_addr2sockaddr (context, &addrs.val[i], sa, &sa_size, port); sockets[i] = socket (sa->sa_family, SOCK_DGRAM, 0); if (sockets[i] < 0) krb5_err (context, 1, errno, "socket"); if (bind (sockets[i], sa, sa_size) < 0) { char str[128]; size_t len; int save_errno = errno; ret = krb5_print_address (&addrs.val[i], str, sizeof(str), &len); if (ret) strlcpy(str, "unknown address", sizeof(str)); krb5_warn (context, save_errno, "bind(%s)", str); continue; } maxfd = max (maxfd, sockets[i]); if (maxfd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); FD_SET(sockets[i], &real_fdset); } #ifdef INETD_SUPPORT } else { n = 1; maxfd = 0; fdz = 0; sockets = &fdz; FD_ZERO(&real_fdset); FD_SET(0, &real_fdset); } #endif if (maxfd == -1) krb5_errx (context, 1, "No sockets!"); while(exit_flag == 0) { krb5_ssize_t retx; fd_set fdset = real_fdset; retx = select (maxfd + 1, &fdset, NULL, NULL, NULL); if (retx < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } for (i = 0; i < n; ++i) if (FD_ISSET(sockets[i], &fdset)) { u_char buf[BUFSIZ]; socklen_t addrlen = sizeof(__ss); retx = recvfrom(sockets[i], buf, sizeof(buf), 0, sa, &addrlen); if (retx < 0) { if(errno == EINTR) break; else krb5_err (context, 1, errno, "recvfrom"); } #ifdef INETD_SUPPORT if (from_inetd) { socklen_t loclen = sizeof(__local); int ret2; ret2 = get_local_addr(sa, addrlen, localsa, &loclen); if (ret2 < 0) krb5_errx (context, errno, "get_local_addr"); ret2 = krb5_sockaddr2address(context, localsa, &my_addr); if (ret2) krb5_errx (context, ret2, "krb5_sockaddr2address"); my_addrp = &my_addr; } else #endif my_addrp = &addrs.val[i]; process (realms, keytab, sockets[i], my_addrp, sa, addrlen, buf, retx); #ifdef INETD_SUPPORT if (from_inetd) { krb5_free_address(context, &my_addr); } #endif } #ifdef INETD_SUPPORT if (from_inetd) break; #endif } for (i = 0; i < n; ++i) close(sockets[i]); free(sockets); #ifdef INETD_SUPPORT if (!from_inetd) #endif krb5_free_addresses (context, &addrs); krb5_free_host_realm (context, realms); krb5_free_context (context); return 0; }
static void process (krb5_realm *realms, krb5_keytab keytab, int s, krb5_address *this_addr, struct sockaddr *sa, int sa_size, u_char *msg, int len) { krb5_error_code ret; krb5_auth_context auth_context = NULL; krb5_data out_data; krb5_ticket *ticket; krb5_address other_addr; uint16_t version; memset(&other_addr, 0, sizeof(other_addr)); krb5_data_zero (&out_data); ret = krb5_auth_con_init (context, &auth_context); if (ret) { krb5_warn (context, ret, "krb5_auth_con_init"); return; } krb5_auth_con_setflags (context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); ret = krb5_sockaddr2address (context, sa, &other_addr); if (ret) { krb5_warn (context, ret, "krb5_sockaddr2address"); goto out; } ret = krb5_auth_con_setaddrs (context, auth_context, this_addr, NULL); if (ret) { krb5_warn (context, ret, "krb5_auth_con_setaddr(this)"); goto out; } if (verify (&auth_context, realms, keytab, &ticket, &out_data, &version, s, sa, sa_size, msg, len, &other_addr) == 0) { /* * We always set the client_addr, to assume that the client * can ignore it if it choose to do so (just the server does * so for addressless tickets). */ ret = krb5_auth_con_setaddrs (context, auth_context, this_addr, &other_addr); if (ret) { krb5_warn (context, ret, "krb5_auth_con_setaddr(other)"); goto out; } change (auth_context, ticket->client, version, s, sa, sa_size, &out_data); memset (out_data.data, 0, out_data.length); krb5_free_ticket (context, ticket); } out: krb5_free_address(context, &other_addr); krb5_data_free(&out_data); krb5_auth_con_free(context, auth_context); }
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi) { krb5_error_code ret; struct gensec_krb5_state *gensec_krb5_state; struct cli_credentials *creds; const struct socket_address *my_addr, *peer_addr; krb5_address my_krb5_addr, peer_krb5_addr; creds = gensec_get_credentials(gensec_security); if (!creds) { return NT_STATUS_INVALID_PARAMETER; } gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state); if (!gensec_krb5_state) { return NT_STATUS_NO_MEMORY; } gensec_security->private_data = gensec_krb5_state; gensec_krb5_state->smb_krb5_context = NULL; gensec_krb5_state->auth_context = NULL; gensec_krb5_state->ticket = NULL; ZERO_STRUCT(gensec_krb5_state->enc_ticket); gensec_krb5_state->keyblock = NULL; gensec_krb5_state->session_key = data_blob(NULL, 0); gensec_krb5_state->pac = data_blob(NULL, 0); gensec_krb5_state->gssapi = gssapi; talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); if (cli_credentials_get_krb5_context(creds, gensec_security->event_ctx, gensec_security->settings->lp_ctx, &gensec_krb5_state->smb_krb5_context)) { talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } my_addr = gensec_get_my_addr(gensec_security); if (my_addr && my_addr->sockaddr) { ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, my_addr->sockaddr, &my_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } peer_addr = gensec_get_peer_addr(gensec_security); if (peer_addr && peer_addr->sockaddr) { ret = krb5_sockaddr2address(gensec_krb5_state->smb_krb5_context->krb5_context, peer_addr->sockaddr, &peer_krb5_addr); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_sockaddr2address (local) failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } } ret = krb5_auth_con_setaddrs(gensec_krb5_state->smb_krb5_context->krb5_context, gensec_krb5_state->auth_context, my_addr ? &my_krb5_addr : NULL, peer_addr ? &peer_krb5_addr : NULL); if (ret) { DEBUG(1,("gensec_krb5_start: krb5_auth_con_setaddrs failed (%s)\n", smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state))); talloc_free(gensec_krb5_state); return NT_STATUS_INTERNAL_ERROR; } return NT_STATUS_OK; }
static krb5_error_code find_all_addresses (krb5_context context, krb5_addresses *res, int flags) { struct sockaddr sa_zero; struct ifaddrs *ifa0, *ifa; krb5_error_code ret = ENXIO; unsigned int num, idx; krb5_addresses ignore_addresses; if (getifaddrs(&ifa0) == -1) { ret = errno; krb5_set_error_message(context, ret, "getifaddrs: %s", strerror(ret)); return (ret); } memset(&sa_zero, 0, sizeof(sa_zero)); /* First, count all the ifaddrs. */ for (ifa = ifa0, num = 0; ifa != NULL; ifa = ifa->ifa_next, num++) /* nothing */; if (num == 0) { freeifaddrs(ifa0); krb5_set_error_message(context, ENXIO, N_("no addresses found", "")); return (ENXIO); } if (flags & EXTRA_ADDRESSES) { /* we'll remove the addresses we don't care about */ ret = krb5_get_ignore_addresses(context, &ignore_addresses); if(ret) return ret; } /* Allocate storage for them. */ res->val = calloc(num, sizeof(*res->val)); if (res->val == NULL) { if (flags & EXTRA_ADDRESSES) krb5_free_addresses(context, &ignore_addresses); freeifaddrs(ifa0); krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } /* Now traverse the list. */ for (ifa = ifa0, idx = 0; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_flags & IFF_UP) == 0) continue; if (ifa->ifa_addr == NULL) continue; if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) continue; if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) continue; if (krb5_sockaddr_is_loopback(ifa->ifa_addr) && (flags & LOOP) == 0) /* We'll deal with the LOOP_IF_NONE case later. */ continue; ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); if (ret) { /* * The most likely error here is going to be "Program * lacks support for address type". This is no big * deal -- just continue, and we'll listen on the * addresses who's type we *do* support. */ continue; } /* possibly skip this address? */ if((flags & EXTRA_ADDRESSES) && krb5_address_search(context, &res->val[idx], &ignore_addresses)) { krb5_free_address(context, &res->val[idx]); flags &= ~LOOP_IF_NONE; /* we actually found an address, so don't add any loop-back addresses */ continue; } idx++; } /* * If no addresses were found, and LOOP_IF_NONE is set, then find * the loopback addresses and add them to our list. */ if ((flags & LOOP_IF_NONE) != 0 && idx == 0) { for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_flags & IFF_UP) == 0) continue; if (ifa->ifa_addr == NULL) continue; if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) continue; if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) continue; if (!krb5_sockaddr_is_loopback(ifa->ifa_addr)) continue; if ((ifa->ifa_flags & IFF_LOOPBACK) == 0) /* Presumably loopback addrs are only used on loopback ifs! */ continue; ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); if (ret) continue; /* We don't consider this failure fatal */ if((flags & EXTRA_ADDRESSES) && krb5_address_search(context, &res->val[idx], &ignore_addresses)) { krb5_free_address(context, &res->val[idx]); continue; } idx++; } } if (flags & EXTRA_ADDRESSES) krb5_free_addresses(context, &ignore_addresses); freeifaddrs(ifa0); if (ret) { free(res->val); res->val = NULL; } else res->len = idx; /* Now a count. */ return (ret); }
static int proto (int sock, const char *service) { struct sockaddr_storage remote, local; socklen_t addrlen; krb5_address remote_addr, local_addr; krb5_ccache ccache; krb5_auth_context auth_context; krb5_error_code status; krb5_data packet; krb5_data data; krb5_data client_name; krb5_creds in_creds, *out_creds; addrlen = sizeof(local); if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 || addrlen > sizeof(local)) err (1, "getsockname)"); addrlen = sizeof(remote); if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 || addrlen > sizeof(remote)) err (1, "getpeername"); status = krb5_auth_con_init (context, &auth_context); if (status) krb5_err(context, 1, status, "krb5_auth_con_init"); status = krb5_sockaddr2address (context, (struct sockaddr *)&local, &local_addr); if (status) krb5_err(context, 1, status, "krb5_sockaddr2address(local)"); status = krb5_sockaddr2address (context, (struct sockaddr *)&remote, &remote_addr); if (status) krb5_err(context, 1, status, "krb5_sockaddr2address(remote)"); status = krb5_auth_con_setaddrs (context, auth_context, &local_addr, &remote_addr); if (status) krb5_err(context, 1, status, "krb5_auth_con_setaddr"); status = krb5_read_message(context, &sock, &client_name); if(status) krb5_err(context, 1, status, "krb5_read_message"); memset(&in_creds, 0, sizeof(in_creds)); status = krb5_cc_default(context, &ccache); if(status) krb5_err(context, 1, status, "krb5_cc_default"); status = krb5_cc_get_principal(context, ccache, &in_creds.client); if(status) krb5_err(context, 1, status, "krb5_cc_get_principal"); status = krb5_read_message(context, &sock, &in_creds.second_ticket); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_parse_name(context, client_name.data, &in_creds.server); if(status) krb5_err(context, 1, status, "krb5_parse_name"); status = krb5_get_credentials(context, KRB5_GC_USER_USER, ccache, &in_creds, &out_creds); if(status) krb5_err(context, 1, status, "krb5_get_credentials"); status = krb5_cc_default(context, &ccache); if(status) krb5_err(context, 1, status, "krb5_cc_default"); status = krb5_sendauth(context, &auth_context, &sock, VERSION, in_creds.client, in_creds.server, AP_OPTS_USE_SESSION_KEY, NULL, out_creds, ccache, NULL, NULL, NULL); if (status) krb5_err(context, 1, status, "krb5_sendauth"); { char *str; krb5_unparse_name(context, in_creds.server, &str); printf ("User is `%s'\n", str); free(str); krb5_unparse_name(context, in_creds.client, &str); printf ("Server is `%s'\n", str); free(str); } krb5_data_zero (&data); krb5_data_zero (&packet); status = krb5_read_message(context, &sock, &packet); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_rd_safe (context, auth_context, &packet, &data, NULL); if (status) krb5_err(context, 1, status, "krb5_rd_safe"); printf ("safe packet: %.*s\n", (int)data.length, (char *)data.data); status = krb5_read_message(context, &sock, &packet); if(status) krb5_err(context, 1, status, "krb5_read_message"); status = krb5_rd_priv (context, auth_context, &packet, &data, NULL); if (status) krb5_err(context, 1, status, "krb5_rd_priv"); printf ("priv packet: %.*s\n", (int)data.length, (char *)data.data); return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_parse_address(krb5_context context, const char *string, krb5_addresses *addresses) { int i, n; struct addrinfo *ai, *a; int error; int save_errno; addresses->len = 0; addresses->val = NULL; for(i = 0; i < num_addrs; i++) { if(at[i].parse_addr) { krb5_address addr; if((*at[i].parse_addr)(context, string, &addr) == 0) { ALLOC_SEQ(addresses, 1); if (addresses->val == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } addresses->val[0] = addr; return 0; } } } error = getaddrinfo (string, NULL, NULL, &ai); if (error) { krb5_error_code ret2; save_errno = errno; ret2 = krb5_eai_to_heim_errno(error, save_errno); krb5_set_error_message (context, ret2, "%s: %s", string, gai_strerror(error)); return ret2; } n = 0; for (a = ai; a != NULL; a = a->ai_next) ++n; ALLOC_SEQ(addresses, n); if (addresses->val == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); freeaddrinfo(ai); return ENOMEM; } addresses->len = 0; for (a = ai, i = 0; a != NULL; a = a->ai_next) { if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i])) continue; if(krb5_address_search(context, &addresses->val[i], addresses)) { krb5_free_address(context, &addresses->val[i]); continue; } i++; addresses->len = i; } freeaddrinfo (ai); return 0; }