Example #1
0
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;

}
Example #2
0
File: 524.c Project: gojdic/samba
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;
}
Example #3
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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);
}
Example #8
0
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;
}
Example #9
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;
}
Example #10
0
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;
}
Example #11
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);
}
Example #12
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 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;
}
Example #13
0
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);
}
Example #14
0
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;
}
Example #15
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;
}