⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 krb5-security.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    set_root_privs(1);    server_socket = stream_client(rc->hostname,				     (in_port_t)(ntohs(port)),				     STREAM_BUFSIZE,				     STREAM_BUFSIZE,				     &my_port,				     0);    set_root_privs(0);    if(server_socket < 0) {	security_seterror(&rh->sech,	    "%s", strerror(errno));		return -1;    }    rc->read = rc->write = server_socket;    if (gss_client(rh) < 0) {	return -1;    }    return 0;}/* * Negotiate a krb5 gss context from the client end. */static intgss_client(    struct sec_handle *rh){    struct sec_stream *rs = rh->rs;    struct tcp_conn *rc = rs->rc;    gss_buffer_desc send_tok, recv_tok, AA;    gss_OID doid;    OM_uint32 maj_stat, min_stat;    unsigned int ret_flags;    int rval = -1;    int rvalue;    gss_name_t gss_name;    char *errmsg = NULL;    auth_debug(1, "gss_client\n");    send_tok.value = vstralloc("host/", rs->rc->hostname, NULL);    send_tok.length = strlen(send_tok.value) + 1;    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID,	&gss_name);    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {	security_seterror(&rh->sech, _("can't import name %s: %s"),	    (char *)send_tok.value, gss_error(maj_stat, min_stat));	amfree(send_tok.value);	return (-1);    }    amfree(send_tok.value);    rc->gss_context = GSS_C_NO_CONTEXT;    maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid);    dbprintf(_("gss_name %s\n"), (char *)AA.value);    /*     * Perform the context-establishement loop.     *     * Every generated token is stored in send_tok which is then     * transmitted to the server; every received token is stored in     * recv_tok (empty on the first pass) to be processed by     * the next call to gss_init_sec_context.     *      * GSS-API guarantees that send_tok's length will be non-zero     * if and only if the server is expecting another token from us,     * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if     * and only if the server has another token to send us.     */    recv_tok.value = NULL;    for (recv_tok.length = 0;;) {	min_stat = 0;	maj_stat = gss_init_sec_context(&min_stat,	    GSS_C_NO_CREDENTIAL,	    &rc->gss_context,	    gss_name,	    GSS_C_NULL_OID,	    (OM_uint32)GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG,	    0, NULL,	/* no channel bindings */	    (recv_tok.length == 0 ? GSS_C_NO_BUFFER : &recv_tok),	    NULL,	/* ignore mech type */	    &send_tok,	    &ret_flags,	    NULL);	/* ignore time_rec */	if (recv_tok.length != 0) {	    amfree(recv_tok.value);	    recv_tok.length = 0;	}	if (maj_stat != (OM_uint32)GSS_S_COMPLETE && maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) {	    security_seterror(&rh->sech,		_("error getting gss context: %s %s"),		gss_error(maj_stat, min_stat), (char *)send_tok.value);	    goto done;	}	/*	 * Send back the response	 */	if (send_tok.length != 0 && tcpm_send_token(rc, rc->write, rs->handle, &errmsg, send_tok.value, send_tok.length) < 0) {	    security_seterror(&rh->sech, rc->errmsg);	    gss_release_buffer(&min_stat, &send_tok);	    goto done;	}	gss_release_buffer(&min_stat, &send_tok);	/*	 * If we need to continue, then register for more packets	 */	if (maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED)	    break;        rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg,				 (void *)&recv_tok.value,				 (ssize_t *)&recv_tok.length, 60);	if (rvalue <= 0) {	    if (rvalue < 0)		security_seterror(&rh->sech,		    _("recv error in gss loop: %s"), rc->errmsg);	    else		security_seterror(&rh->sech, _("EOF in gss loop"));	    goto done;	}    }    rval = 0;    rc->auth = 1;done:    gss_release_name(&min_stat, &gss_name);    return (rval);}/* * Negotiate a krb5 gss context from the server end. */static intgss_server(    struct tcp_conn *rc){    OM_uint32 maj_stat, min_stat, ret_flags;    gss_buffer_desc send_tok, recv_tok, AA;    gss_OID doid;    gss_name_t gss_name;    gss_cred_id_t gss_creds;    char *p, *realm, *msg;    uid_t euid;    int rval = -1;    int rvalue;    char errbuf[256];    char *errmsg = NULL;    auth_debug(1, "gss_server\n");    assert(rc != NULL);    /*     * We need to be root while in gss_acquire_cred() to read the host key     * out of the default keytab.  We also need to be root in     * gss_accept_context() thanks to the replay cache code.     */    euid = geteuid();    if (getuid() != 0) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("real uid is %ld, needs to be 0 to read krb5 host key"),	    (long)getuid());	goto out;    }    if (!set_root_privs(0)) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("can't seteuid to uid 0: %s"), strerror(errno));	goto out;    }    rc->gss_context = GSS_C_NO_CONTEXT;    send_tok.value = vstralloc("host/", myhostname, NULL);    send_tok.length = strlen(send_tok.value) + 1;    for (p = send_tok.value; *p != '\0'; p++) {	if (isupper((int)*p))	    *p = tolower(*p);    }    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID,	&gss_name);    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {	set_root_privs(0);	g_snprintf(errbuf, SIZEOF(errbuf),	    _("can't import name %s: %s"), (char *)send_tok.value,	    gss_error(maj_stat, min_stat));	amfree(send_tok.value);	goto out;    }    amfree(send_tok.value);    maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid);    dbprintf(_("gss_name %s\n"), (char *)AA.value);    maj_stat = gss_acquire_cred(&min_stat, gss_name, 0,	GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &gss_creds, NULL, NULL);    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("can't acquire creds for host key host/%s: %s"), myhostname,	    gss_error(maj_stat, min_stat));	gss_release_name(&min_stat, &gss_name);	set_root_privs(0);	goto out;    }    gss_release_name(&min_stat, &gss_name);    for (recv_tok.length = 0;;) {	recv_tok.value = NULL;        rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg,				 /* (void *) is to avoid type-punning warning */				 (char **)(void *)&recv_tok.value,				 (ssize_t *)&recv_tok.length, 60);	if (rvalue <= 0) {	    if (rvalue < 0) {		g_snprintf(errbuf, SIZEOF(errbuf),		    _("recv error in gss loop: %s"), rc->errmsg);		amfree(rc->errmsg);	    } else		g_snprintf(errbuf, SIZEOF(errbuf), _("EOF in gss loop"));	    goto out;	}	maj_stat = gss_accept_sec_context(&min_stat, &rc->gss_context,	    gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS,	    &gss_name, &doid, &send_tok, &ret_flags, NULL, NULL);	if (maj_stat != (OM_uint32)GSS_S_COMPLETE &&	    maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) {	    g_snprintf(errbuf, SIZEOF(errbuf),		_("error accepting context: %s"), gss_error(maj_stat, min_stat));	    amfree(recv_tok.value);	    goto out;	}	amfree(recv_tok.value);	if (send_tok.length != 0 && tcpm_send_token(rc, rc->write, 0, &errmsg, send_tok.value, send_tok.length) < 0) {	    strncpy(errbuf, rc->errmsg, SIZEOF(errbuf) - 1);	    errbuf[SIZEOF(errbuf) - 1] = '\0';	    amfree(rc->errmsg);	    gss_release_buffer(&min_stat, &send_tok);	    goto out;	}	gss_release_buffer(&min_stat, &send_tok);	/*	 * If we need to get more from the client, then register for	 * more packets.	 */	if (maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED)	    break;    }    maj_stat = gss_display_name(&min_stat, gss_name, &send_tok, &doid);    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("can't display gss name: %s"), gss_error(maj_stat, min_stat));	gss_release_name(&min_stat, &gss_name);	goto out;    }    gss_release_name(&min_stat, &gss_name);    /* get rid of the realm */    if ((p = strchr(send_tok.value, '@')) == NULL) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("malformed gss name: %s"), (char *)send_tok.value);	amfree(send_tok.value);	goto out;    }    *p = '\0';    realm = ++p;    /*      * If the principal doesn't match, complain     */    if ((msg = krb5_checkuser(rc->hostname, send_tok.value, realm)) != NULL) {	g_snprintf(errbuf, SIZEOF(errbuf),	    _("access not allowed from %s: %s"), (char *)send_tok.value, msg);	amfree(send_tok.value);	goto out;    }    amfree(send_tok.value);    rval = 0;out:    set_root_privs(0);    if (rval != 0) {	rc->errmsg = stralloc(errbuf);    } else {	rc->auth = 1;    }    auth_debug(1, _("gss_server returning %d\n"), rval);    return (rval);}/* * Setup some things about krb5.  This should only be called once. */static voidkrb5_init(void){    static int beenhere = 0;    char *p;    char *myfqhostname=NULL;    if (beenhere)	return;    beenhere = 1;#ifndef BROKEN_MEMORY_CCACHE    putenv(stralloc("KRB5_ENV_CCNAME=MEMORY:amanda_ccache"));#else    /*     * MEMORY ccaches seem buggy and cause a lot of internal heap     * corruption.  malloc has been known to core dump.  This behavior     * has been witnessed in Cygnus' kerbnet 1.2, MIT's krb V 1.0.5 and     * MIT's krb V -current as of 3/17/1999.     *     * We just use a lame ccache scheme with a uid suffix.     */    atexit(cleanup);    {	char *ccache;	ccache = malloc(128);	g_snprintf(ccache, SIZEOF(ccache),		 "KRB5_ENV_CCNAME=FILE:/tmp/amanda_ccache.%ld.%ld",		 (long)geteuid(), (long)getpid());	putenv(ccache);    }#endif    gethostname(myhostname, SIZEOF(myhostname) - 1);    myhostname[SIZEOF(myhostname) - 1] = '\0';    /*     * In case it isn't fully qualified, do a DNS lookup.  Ignore     * any errors (this is best-effort).     */    if (resolve_hostname(myhostname, SOCK_STREAM, NULL, &myfqhostname) == 0	&& myfqhostname != NULL) {	strncpy(myhostname, myfqhostname, SIZEOF(myhostname)-1);	myhostname[SIZEOF(myhostname)-1] = '\0';	amfree(myfqhostname);    }    /*     * Lowercase the results.  We assume all host/ principals will be     * lowercased.     */    for (p = myhostname; *p != '\0'; p++) {	if (isupper((int)*p))	    *p = tolower(*p);    }}#ifdef BROKEN_MEMORY_CCACHEstatic voidcleanup(void){#ifdef KDESTROY_VIA_UNLINK    char ccache[64];    g_snprintf(ccache, SIZEOF(ccache), "/tmp/amanda_ccache.%ld.%ld",        (long)geteuid(), (long)getpid());    unlink(ccache);#else    kdestroy();#endif}#endif/* * Get a ticket granting ticket and stuff it in the cache */static const char *get_tgt(    char *	keytab_name,    char *	principal_name){    krb5_context context;    krb5_error_code ret;    krb5_principal client = NULL, server = NULL;    krb5_creds creds;    krb5_keytab keytab;    krb5_ccache ccache;    krb5_timestamp now;#ifdef KRB5_HEIMDAL_INCLUDES    krb5_data tgtname = { KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };#else    krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };#endif    static char *error = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -