コード例 #1
0
ファイル: getnameinfo_verified.c プロジェクト: 2asoft/freebsd
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
		     char *host, size_t hostlen,
		     char *serv, size_t servlen,
		     int flags)
{
    int ret;
    struct addrinfo *ai, *a;
    char servbuf[NI_MAXSERV];
    struct addrinfo hints;
    void *saaddr;
    size_t sasize;

    if (host == NULL)
	return EAI_NONAME;

    if (serv == NULL) {
	serv = servbuf;
	servlen = sizeof(servbuf);
    }

    ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
		       flags | NI_NUMERICSERV);
    if (ret)
	goto fail;

    memset (&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    ret = getaddrinfo (host, serv, &hints, &ai);
    if (ret)
	goto fail;

    saaddr = socket_get_address(sa);
    sasize = socket_addr_size(sa);
    for (a = ai; a != NULL; a = a->ai_next) {
	if (sasize == socket_addr_size(a->ai_addr) &&
	    memcmp(saaddr, socket_get_address(a->ai_addr), sasize) == 0) {
	    freeaddrinfo (ai);
	    return 0;
	}
    }
    freeaddrinfo (ai);
 fail:
    if (flags & NI_NAMEREQD)
	return EAI_NONAME;
    ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
		       flags | NI_NUMERICSERV | NI_NUMERICHOST);
    return ret;
}
コード例 #2
0
ファイル: socket.c プロジェクト: 0-14N/NDroid
/*
 * XXX This should really be tcp_listen
 */
struct socket *
solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
{
	SockAddress  addr;
	uint32_t     addr_ip;
	struct socket *so;
	int s;

	DEBUG_CALL("solisten");
	DEBUG_ARG("port = %d", port);
	DEBUG_ARG("laddr = %x", laddr);
	DEBUG_ARG("lport = %d", lport);
	DEBUG_ARG("flags = %x", flags);

	if ((so = socreate()) == NULL) {
	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
	  return NULL;
	}

	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
		free(so);
		return NULL;
	}
	insque(so,&tcb);

	/*
	 * SS_FACCEPTONCE sockets must time out.
	 */
	if (flags & SS_FACCEPTONCE)
	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;

	so->so_state      = (SS_FACCEPTCONN|flags);
	so->so_laddr_port = lport; /* Kept in host format */
    so->so_laddr_ip   = laddr; /* Ditto */
    so->so_haddr_port = port;

    s = socket_loopback_server( port, SOCKET_STREAM );
    if (s < 0)
        return NULL;

    socket_get_address(s, &addr);

	so->so_faddr_port = sock_address_get_port(&addr);

    addr_ip = (uint32_t) sock_address_get_ip(&addr);

    if (addr_ip == 0 || addr_ip == loopback_addr_ip)
        so->so_faddr_ip = alias_addr_ip;
    else
        so->so_faddr_ip = addr_ip;

	so->s = s;
	return so;
}
コード例 #3
0
ファイル: getaddrinfo-test.c プロジェクト: 2asoft/freebsd
static void
doit (const char *nodename, const char *servname)
{
    struct addrinfo hints;
    struct addrinfo *res, *r;
    int ret;

    if (verbose_counter)
	printf ("(%s,%s)... ", nodename ? nodename : "null", servname);

    memset (&hints, 0, sizeof(hints));
    hints.ai_flags    = flags;
    hints.ai_family   = family;
    hints.ai_socktype = socktype;

    ret = getaddrinfo (nodename, servname, &hints, &res);
    if (ret)
	errx(1, "error: %s\n", gai_strerror(ret));

    if (verbose_counter)
	printf ("\n");

    for (r = res; r != NULL; r = r->ai_next) {
	char addrstr[256];

	if (inet_ntop (r->ai_family,
		       socket_get_address (r->ai_addr),
		       addrstr, sizeof(addrstr)) == NULL) {
	    if (verbose_counter)
		printf ("\tbad address?\n");
	    continue;
	}
	if (verbose_counter) {
	    printf ("\tfamily = %d, socktype = %d, protocol = %d, "
		    "address = \"%s\", port = %d",
		    r->ai_family, r->ai_socktype, r->ai_protocol,
		    addrstr,
		    ntohs(socket_get_port (r->ai_addr)));
	    if (r->ai_canonname)
		printf (", canonname = \"%s\"", r->ai_canonname);
	    printf ("\n");
	}
    }
    freeaddrinfo (res);
}
コード例 #4
0
ファイル: udp.c プロジェクト: flwh/Alcatel_OT_985_kernel
struct socket *
udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
{
	struct socket *so;
	SockAddress    addr;
	uint32_t       addr_ip;

	if ((so = socreate()) == NULL) {
		free(so);
		return NULL;
	}
	so->s = socket_anyaddr_server( port, SOCKET_DGRAM );
	so->so_expire = curtime + SO_EXPIRE;
    so->so_haddr_port = port;
	insque(so,&udb);

	if (so->s < 0) {
		udp_detach(so);
		return NULL;
	}

        socket_get_address(so->s, &addr);

	so->so_faddr_port = sock_address_get_port(&addr);
	addr_ip = sock_address_get_ip(&addr);

	if (addr_ip == 0 || addr_ip == loopback_addr_ip)
	   so->so_faddr_ip = alias_addr_ip;
	else
	   so->so_faddr_ip = addr_ip;

	so->so_laddr_port = lport;
	so->so_laddr_ip   = laddr;
	if (flags != SS_FACCEPTONCE)
	   so->so_expire = 0;

	so->so_state = SS_ISFCONNECTED;

	return so;
}
コード例 #5
0
ファイル: udp.c プロジェクト: flwh/Alcatel_OT_985_kernel
static void
udp_emu(struct socket *so, struct mbuf *m)
{
        SockAddress  sockaddr;

struct cu_header {
	uint16_t	d_family;		// destination family
	uint16_t	d_port;			// destination port
	uint32_t	d_addr;			// destination address
	uint16_t	s_family;		// source family
	uint16_t	s_port;			// source port
	uint32_t	so_addr;		// source address
	uint32_t	seqn;			// sequence number
	uint16_t	message;		// message
	uint16_t	data_type;		// data type
	uint16_t	pkt_len;		// packet length
} *cu_head;

	switch(so->so_emu) {

	case EMU_CUSEEME:

		/*
		 * Cu-SeeMe emulation.
		 * Hopefully the packet is more that 16 bytes long. We don't
		 * do any other tests, just replace the address and port
		 * fields.
		 */
		if (m->m_len >= sizeof (*cu_head)) {
			if (socket_get_address(so->s, &sockaddr) < 0)
                            return;

			cu_head = mtod(m, struct cu_header *);
			cu_head->s_port  = htons( sock_address_get_port(&sockaddr));
			cu_head->so_addr = htonl( sock_address_get_ip(&sockaddr));
		}

		return;
	}
}
コード例 #6
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_auth_context ac = NULL;
    krb5_principal c1, c2;
    krb5_authenticator authent;
    krb5_keytab keytab;
    krb5_socket_t sock = rk_INVALID_SOCKET;
    HDB *db = NULL;
    int optidx = 0;
    char *tmp_db;
    krb5_log_facility *fac;
    int nprincs;

    setprogname(argv[0]);

    ret = krb5_init_context(&context);
    if(ret)
	exit(1);

    ret = krb5_openlog(context, "hpropd", &fac);
    if(ret)
	errx(1, "krb5_openlog");
    krb5_set_warn_dest(context, fac);

    if(getarg(args, num_args, argc, argv, &optidx))
	usage(1);

    if(local_realm != NULL)
	krb5_set_default_realm(context, local_realm);

    if(help_flag)
	usage(0);
    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 0)
	usage(1);

    if (database == NULL)
	database = hdb_default_db(context);

    if(from_stdin) {
	sock = STDIN_FILENO;
    } else {
	struct sockaddr_storage ss;
	struct sockaddr *sa = (struct sockaddr *)&ss;
	socklen_t sin_len = sizeof(ss);
	char addr_name[256];
	krb5_ticket *ticket;
	char *server;

	sock = STDIN_FILENO;
#ifdef SUPPORT_INETD
	if (inetd_flag == -1) {
	    if (getpeername (sock, sa, &sin_len) < 0) {
		inetd_flag = 0;
	    } else {
		inetd_flag = 1;
	    }
	}
#else
	inetd_flag = 0;
#endif
	if (!inetd_flag) {
	    mini_inetd (krb5_getportbyname (context, "hprop", "tcp",
					    HPROP_PORT), &sock);
	}
	sin_len = sizeof(ss);
	if(getpeername(sock, sa, &sin_len) < 0)
	    krb5_err(context, 1, errno, "getpeername");

	if (inet_ntop(sa->sa_family,
		      socket_get_address (sa),
		      addr_name,
		      sizeof(addr_name)) == NULL)
	    strlcpy (addr_name, "unknown address",
		     sizeof(addr_name));

	krb5_log(context, fac, 0, "Connection from %s", addr_name);

	ret = krb5_kt_register(context, &hdb_kt_ops);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_kt_register");

	if (ktname != NULL) {
	    ret = krb5_kt_resolve(context, ktname, &keytab);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname);
	} else {
	    ret = krb5_kt_default (context, &keytab);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_kt_default");
	}

	ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL,
			    0, keytab, &ticket);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_recvauth");

	ret = krb5_unparse_name(context, ticket->server, &server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_unparse_name");
	if (strncmp(server, "hprop/", 5) != 0)
	    krb5_errx(context, 1, "ticket not for hprop (%s)", server);

	free(server);
	krb5_free_ticket (context, ticket);

	ret = krb5_auth_con_getauthenticator(context, ac, &authent);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator");

	ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_make_principal");
	_krb5_principalname2krb5_principal(context, &c2,
					   authent->cname, authent->crealm);
	if(!krb5_principal_compare(context, c1, c2)) {
	    char *s;
	    ret = krb5_unparse_name(context, c2, &s);
	    if (ret)
		s = unparseable_name;
	    krb5_errx(context, 1, "Unauthorized connection from %s", s);
	}
	krb5_free_principal(context, c1);
	krb5_free_principal(context, c2);

	ret = krb5_kt_close(context, keytab);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_kt_close");
    }

    if(!print_dump) {
	asprintf(&tmp_db, "%s~", database);

	ret = hdb_create(context, &db, tmp_db);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
	ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
    }

    nprincs = 0;
    while(1){
	krb5_data data;
	hdb_entry_ex entry;

	if(from_stdin) {
	    ret = krb5_read_message(context, &sock, &data);
	    if(ret != 0 && ret != HEIM_ERR_EOF)
		krb5_err(context, 1, ret, "krb5_read_message");
	} else {
	    ret = krb5_read_priv_message(context, ac, &sock, &data);
	    if(ret)
		krb5_err(context, 1, ret, "krb5_read_priv_message");
	}

	if(ret == HEIM_ERR_EOF || data.length == 0) {
	    if(!from_stdin) {
		data.data = NULL;
		data.length = 0;
		krb5_write_priv_message(context, ac, &sock, &data);
	    }
	    if(!print_dump) {
		ret = db->hdb_close(context, db);
		if(ret)
		    krb5_err(context, 1, ret, "db_close");
		ret = db->hdb_rename(context, db, database);
		if(ret)
		    krb5_err(context, 1, ret, "db_rename");
	    }
	    break;
	}
	memset(&entry, 0, sizeof(entry));
	ret = hdb_value2entry(context, &data, &entry.entry);
	krb5_data_free(&data);
	if(ret)
	    krb5_err(context, 1, ret, "hdb_value2entry");
	if(print_dump)
	    hdb_print_entry(context, db, &entry, stdout);
	else {
	    ret = db->hdb_store(context, db, 0, &entry);
	    if(ret == HDB_ERR_EXISTS) {
		char *s;
		ret = krb5_unparse_name(context, entry.entry.principal, &s);
		if (ret)
		    s = strdup(unparseable_name);
		krb5_warnx(context, "Entry exists: %s", s);
		free(s);
	    } else if(ret)
		krb5_err(context, 1, ret, "db_store");
	    else
		nprincs++;
	}
	hdb_free_entry(context, &entry);
    }
    if (!print_dump)
	krb5_log(context, fac, 0, "Received %d principals", nprincs);

    if (inetd_flag == 0)
	rk_closesocket(sock);

    exit(0);
}
コード例 #7
0
ファイル: rshd.c プロジェクト: 2asoft/freebsd
static void
doit (void)
{
    u_char buf[BUFSIZ];
    u_char *p;
    struct sockaddr_storage thisaddr_ss;
    struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
    struct sockaddr_storage thataddr_ss;
    struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
    struct sockaddr_storage erraddr_ss;
    struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
    socklen_t thisaddr_len, thataddr_len;
    int port;
    int errsock = -1;
    char *client_user = NULL, *server_user = NULL, *cmd = NULL;
    struct passwd *pwd;
    int s = STDIN_FILENO;
    char **env;
    int ret;
    char that_host[NI_MAXHOST];

    thisaddr_len = sizeof(thisaddr_ss);
    if (getsockname (s, thisaddr, &thisaddr_len) < 0)
	syslog_and_die("getsockname: %s", strerror(errno));
    thataddr_len = sizeof(thataddr_ss);
    if (getpeername (s, thataddr, &thataddr_len) < 0)
	syslog_and_die ("getpeername: %s", strerror(errno));

    /* check for V4MAPPED addresses? */

    if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr)))
	fatal(s, NULL, "Permission denied.");

    p = buf;
    port = 0;
    for(;;) {
	if (net_read (s, p, 1) != 1)
	    syslog_and_die ("reading port number: %s", strerror(errno));
	if (*p == '\0')
	    break;
	else if (isdigit(*p))
	    port = port * 10 + *p - '0';
	else
	    syslog_and_die ("non-digit in port number: %c", *p);
    }

    if (do_kerberos  == 0 && !is_reserved(htons(port)))
	fatal(s, NULL, "Permission denied.");

    if (port) {
	int priv_port = IPPORT_RESERVED - 1;

	/*
	 * There's no reason to require a ``privileged'' port number
	 * here, but for some reason the brain dead rsh clients
	 * do... :-(
	 */

	erraddr->sa_family = thataddr->sa_family;
	socket_set_address_and_port (erraddr,
				     socket_get_address (thataddr),
				     htons(port));

	/*
	 * we only do reserved port for IPv4
	 */

	if (erraddr->sa_family == AF_INET)
	    errsock = rresvport (&priv_port);
	else
	    errsock = socket (erraddr->sa_family, SOCK_STREAM, 0);
	if (errsock < 0)
	    syslog_and_die ("socket: %s", strerror(errno));
	if (connect (errsock,
		     erraddr,
		     socket_sockaddr_size (erraddr)) < 0) {
	    syslog (LOG_WARNING, "connect: %s", strerror(errno));
	    close (errsock);
	}
    }

    if(do_kerberos) {
	if (net_read (s, buf, 4) != 4)
	    syslog_and_die ("reading auth info: %s", strerror(errno));

#ifdef KRB5
	    if((do_kerberos & DO_KRB5) &&
	       recv_krb5_auth (s, buf, thisaddr, thataddr,
			       &client_user,
			       &server_user,
			       &cmd) == 0)
		auth_method = AUTH_KRB5;
	    else
#endif /* KRB5 */
		syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
				buf[0], buf[1], buf[2], buf[3]);
    } else {
	if(recv_bsd_auth (s, buf,
			  (struct sockaddr_in *)thisaddr,
			  (struct sockaddr_in *)thataddr,
			  &client_user,
			  &server_user,
			  &cmd) == 0) {
	    auth_method = AUTH_BROKEN;
	    if(do_vacuous) {
		printf("Remote host requires Kerberos authentication\n");
		exit(0);
	    }
	} else
	    syslog_and_die("recv_bsd_auth failed");
    }

    if (client_user == NULL || server_user == NULL || cmd == NULL)
	syslog_and_die("mising client/server/cmd");

    pwd = getpwnam (server_user);
    if (pwd == NULL)
	fatal (s, NULL, "Login incorrect.");

    if (*pwd->pw_shell == '\0')
	pwd->pw_shell = _PATH_BSHELL;

    if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0)
	fatal (s, NULL, "Login disabled.");


    ret = getnameinfo_verified (thataddr, thataddr_len,
				that_host, sizeof(that_host),
				NULL, 0, 0);
    if (ret)
	fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret));

    if (login_access(pwd, that_host) == 0) {
	syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s",
	       server_user, that_host);
	fatal(s, NULL, "Permission denied.");
    }

#ifdef HAVE_GETSPNAM
    {
	struct spwd *sp;
	long    today;

	sp = getspnam(server_user);
	if (sp != NULL) {
	    today = time(0)/(24L * 60 * 60);
	    if (sp->sp_expire > 0)
		if (today > sp->sp_expire)
		    fatal(s, NULL, "Account has expired.");
	}
    }
#endif


#ifdef HAVE_SETLOGIN
    if (setlogin(pwd->pw_name) < 0)
	syslog(LOG_ERR, "setlogin() failed: %s", strerror(errno));
#endif

#ifdef HAVE_SETPCRED
    if (setpcred (pwd->pw_name, NULL) == -1)
	syslog(LOG_ERR, "setpcred() failure: %s", strerror(errno));
#endif /* HAVE_SETPCRED */

    /* Apply limits if not root */
    if(pwd->pw_uid != 0) {
	 const char *file = _PATH_LIMITS_CONF;
	 read_limits_conf(file, pwd);
    }

    if (initgroups (pwd->pw_name, pwd->pw_gid) < 0)
	fatal (s, "initgroups", "Login incorrect.");

    if (setgid(pwd->pw_gid) < 0)
	fatal (s, "setgid", "Login incorrect.");

    if (setuid (pwd->pw_uid) < 0)
	fatal (s, "setuid", "Login incorrect.");

    if (chdir (pwd->pw_dir) < 0)
	fatal (s, "chdir", "Remote directory.");

    if (errsock >= 0) {
	if (dup2 (errsock, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
	close (errsock);
    } else {
	if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0)
	    fatal (s, "dup2", "Cannot dup stderr.");
    }

#ifdef KRB5
    {
	int fd;

	if (!do_unique_tkfile)
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%lu",
		     (unsigned long)pwd->pw_uid);
	else if (*tkfile=='\0') {
	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX");
	    fd = mkstemp(tkfile+5);
	    close(fd);
	    unlink(tkfile+5);
	}

	if (kerberos_status)
	    krb5_start_session();
    }
#endif

    setup_environment (&env, pwd);

    if (do_encrypt) {
	setup_copier (errsock >= 0);
    } else {
	if (net_write (s, "", 1) != 1)
	    fatal (s, "net_write", "write failed");
    }

#if defined(KRB5)
    if(k_hasafs()) {
	char cell[64];

	if(do_newpag)
	    k_setpag();

	/* XXX */
       if (kerberos_status) {
	   krb5_ccache ccache;
	   krb5_error_code status;

	   status = krb5_cc_resolve (context, tkfile, &ccache);
	   if (!status) {
	       if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0)
		   krb5_afslog_uid_home(context, ccache, cell, NULL,
					pwd->pw_uid, pwd->pw_dir);
	       krb5_afslog_uid_home(context, ccache, NULL, NULL,
				    pwd->pw_uid, pwd->pw_dir);
	       krb5_cc_close (context, ccache);
	   }
       }
    }
#endif /* KRB5 */
    execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env);
    err(1, "exec %s", pwd->pw_shell);
}
コード例 #8
0
ファイル: rshd.c プロジェクト: 2asoft/freebsd
static int
recv_krb5_auth (int s, u_char *buf,
		struct sockaddr *thisaddr,
		struct sockaddr *thataddr,
		char **client_username,
		char **server_username,
		char **cmd)
{
    uint32_t len;
    krb5_auth_context auth_context = NULL;
    krb5_ticket *ticket;
    krb5_error_code status;
    krb5_data cksum_data;
    krb5_principal server;
    char *str;

    if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
	return -1;
    len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);

    if (net_read(s, buf, len) != len)
	syslog_and_die ("reading auth info: %s", strerror(errno));
    if (len != sizeof(KRB5_SENDAUTH_VERSION)
	|| memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
	syslog_and_die ("bad sendauth version: %.8s", buf);

    status = krb5_sock_to_principal (context,
				     s,
				     "host",
				     KRB5_NT_SRV_HST,
				     &server);
    if (status)
	syslog_and_die ("krb5_sock_to_principal: %s",
			krb5_get_err_text(context, status));

    status = krb5_recvauth_match_version(context,
					 &auth_context,
					 &s,
					 match_kcmd_version,
					 NULL,
					 server,
					 KRB5_RECVAUTH_IGNORE_VERSION,
					 NULL,
					 &ticket);
    krb5_free_principal (context, server);
    if (status)
	syslog_and_die ("krb5_recvauth: %s",
			krb5_get_err_text(context, status));

    *server_username = read_str (s, USERNAME_SZ, "remote username");
    *cmd = read_str (s, ARG_MAX + 1, "command");
    *client_username = read_str (s, ARG_MAX + 1, "local username");

    if(protocol_version == 2) {
	status = krb5_auth_con_getremotesubkey(context, auth_context,
					       &keyblock);
	if(status != 0 || keyblock == NULL)
	    syslog_and_die("failed to get remote subkey");
    } else if(protocol_version == 1) {
	status = krb5_auth_con_getkey (context, auth_context, &keyblock);
	if(status != 0 || keyblock == NULL)
	    syslog_and_die("failed to get key");
    }
    if (status != 0 || keyblock == NULL)
       syslog_and_die ("krb5_auth_con_getkey: %s",
                       krb5_get_err_text(context, status));

    status = krb5_crypto_init(context, keyblock, 0, &crypto);
    if(status)
	syslog_and_die("krb5_crypto_init: %s",
		       krb5_get_err_text(context, status));


    cksum_data.length = asprintf (&str,
				  "%u:%s%s",
				  ntohs(socket_get_port (thisaddr)),
				  *cmd,
				  *server_username);
    if (str == NULL)
	syslog_and_die ("asprintf: out of memory");
    cksum_data.data = str;

    status = krb5_verify_authenticator_checksum(context,
						auth_context,
						cksum_data.data,
						cksum_data.length);

    if (status)
	syslog_and_die ("krb5_verify_authenticator_checksum: %s",
			krb5_get_err_text(context, status));

    free (cksum_data.data);

    if (strncmp (*client_username, "-u ", 3) == 0) {
	do_unique_tkfile = 1;
	memmove (*client_username, *client_username + 3,
		 strlen(*client_username) - 2);
    }

    if (strncmp (*client_username, "-U ", 3) == 0) {
	char *end, *temp_tkfile;

	do_unique_tkfile = 1;
	if (strncmp (*client_username + 3, "FILE:", 5) == 0) {
	    temp_tkfile = tkfile;
	} else {
	    strlcpy (tkfile, "FILE:", sizeof(tkfile));
	    temp_tkfile = tkfile + 5;
	}
	end = strchr(*client_username + 3,' ');
	if (end == NULL)
	    syslog_and_die("missing argument after -U");
	snprintf(temp_tkfile, sizeof(tkfile) - (temp_tkfile - tkfile),
		 "%.*s",
		 (int)(end - *client_username - 3),
		 *client_username + 3);
	memmove (*client_username, end + 1, strlen(end+1)+1);
    }

    kerberos_status = save_krb5_creds (s, auth_context, ticket->client);

    if(!krb5_kuserok (context,
		      ticket->client,
		      *server_username))
	fatal (s, NULL, "Permission denied.");

    if (strncmp (*cmd, "-x ", 3) == 0) {
	do_encrypt = 1;
	memmove (*cmd, *cmd + 3, strlen(*cmd) - 2);
    } else {
	if(do_encrypt)
	    fatal (s, NULL, "Encryption is required.");
	do_encrypt = 0;
    }

    {
	char *name;

	if (krb5_unparse_name (context, ticket->client, &name) == 0) {
	    char addr_str[256];

	    if (inet_ntop (thataddr->sa_family,
			   socket_get_address (thataddr),
			   addr_str, sizeof(addr_str)) == NULL)
		strlcpy (addr_str, "unknown address",
				 sizeof(addr_str));

	    syslog(LOG_INFO|LOG_AUTH,
		   "kerberos v5 shell from %s on %s as %s, cmd '%.80s'",
		   name,
		   addr_str,
		   *server_username,
		   *cmd);
	    free (name);
	}
    }

    krb5_auth_con_free(context, auth_context);

    return 0;
}