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

📄 krb5-security.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (error != NULL) {	amfree(error);	error = NULL;    }    if ((ret = krb5_init_context(&context)) != 0) {	error = vstrallocf(_("error initializing krb5 context: %s"),	    error_message(ret));	return (error);    }    /*krb5_init_ets(context);*/    if(!keytab_name) {        error = vstrallocf(_("error  -- no krb5 keytab defined"));        return(error);    }    if(!principal_name) {        error = vstrallocf(_("error  -- no krb5 principal defined"));        return(error);    }    /*     * Resolve keytab file into a keytab object     */    if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) {	error = vstrallocf(_("error resolving keytab %s: %s"), keytab_name, 	    error_message(ret));	return (error);    }    /*     * Resolve the amanda service held in the keytab into a principal     * object     */    ret = krb5_parse_name(context, principal_name, &client);    if (ret != 0) {	error = vstrallocf(_("error parsing %s: %s"), principal_name,	    error_message(ret));	return (error);    }#ifdef KRB5_HEIMDAL_INCLUDES    ret = krb5_build_principal_ext(context, &server,        krb5_realm_length(*krb5_princ_realm(context, client)),        krb5_realm_data(*krb5_princ_realm(context, client)),        tgtname.length, tgtname.data,        krb5_realm_length(*krb5_princ_realm(context, client)),        krb5_realm_data(*krb5_princ_realm(context, client)),        0);#else    ret = krb5_build_principal_ext(context, &server,	krb5_princ_realm(context, client)->length,	krb5_princ_realm(context, client)->data,	tgtname.length, tgtname.data,	krb5_princ_realm(context, client)->length,	krb5_princ_realm(context, client)->data,	0);#endif    if (ret != 0) {	error = vstrallocf(_("error while building server name: %s"),	    error_message(ret));	return (error);    }    ret = krb5_timeofday(context, &now);    if (ret != 0) {	error = vstrallocf(_("error getting time of day: %s"), error_message(ret));	return (error);    }    memset(&creds, 0, SIZEOF(creds));    creds.times.starttime = 0;    creds.times.endtime = now + AMANDA_TKT_LIFETIME;    creds.client = client;    creds.server = server;    /*     * Get a ticket for the service, using the keytab     */    ret = krb5_get_in_tkt_with_keytab(context, 0, NULL, NULL, NULL,	keytab, 0, &creds, 0);    if (ret != 0) {	error = vstrallocf(_("error getting ticket for %s: %s"),	    principal_name, error_message(ret));	goto cleanup2;    }    if ((ret = krb5_cc_default(context, &ccache)) != 0) {	error = vstrallocf(_("error initializing ccache: %s"), error_message(ret));	goto cleanup;    }    if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) {	error = vstrallocf(_("error initializing ccache: %s"), error_message(ret));	goto cleanup;    }    if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {	error = vstrallocf(_("error storing creds in ccache: %s"), 	    error_message(ret));	/* FALLTHROUGH */    }    krb5_cc_close(context, ccache);cleanup:    krb5_free_cred_contents(context, &creds);cleanup2:#if 0    krb5_free_principal(context, client);    krb5_free_principal(context, server);#endif    krb5_free_context(context);    return (error);}#ifndef KDESTROY_VIA_UNLINK/* * get rid of tickets */static voidkdestroy(void){    krb5_context context;    krb5_ccache ccache;    if ((krb5_init_context(&context)) != 0) {	return;    }    if ((krb5_cc_default(context, &ccache)) != 0) {	goto cleanup;    }    krb5_cc_destroy(context, ccache);    krb5_cc_close(context, ccache);cleanup:     krb5_free_context(context);     return;}#endif/* * Formats an error from the gss api */static const char *gss_error(    OM_uint32	major,    OM_uint32	minor){    static gss_buffer_desc msg;    OM_uint32 min_stat, msg_ctx;    if (msg.length > 0)	gss_release_buffer(&min_stat, &msg);    msg_ctx = 0;    if (major == GSS_S_FAILURE)	gss_display_status(&min_stat, minor, GSS_C_MECH_CODE, GSS_C_NULL_OID,	    &msg_ctx, &msg);    else	gss_display_status(&min_stat, major, GSS_C_GSS_CODE, GSS_C_NULL_OID,	    &msg_ctx, &msg);    return ((const char *)msg.value);}static intk5_encrypt(    void *cookie,    void *buf,    ssize_t buflen,    void **encbuf,    ssize_t *encbuflen){    struct tcp_conn *rc = cookie;    gss_buffer_desc dectok;    gss_buffer_desc enctok;    OM_uint32 maj_stat, min_stat;    int conf_state;    if (rc->conf_fn && rc->conf_fn("kencrypt", rc->datap)) {	auth_debug(1, _("krb5: k5_encrypt: enter %p\n"), rc);	dectok.length = buflen;	dectok.value  = buf;    	if (rc->auth == 1) {	    assert(rc->gss_context != GSS_C_NO_CONTEXT);	    maj_stat = gss_seal(&min_stat, rc->gss_context, 1,			        GSS_C_QOP_DEFAULT, &dectok, &conf_state,				&enctok);	    if (maj_stat != (OM_uint32)GSS_S_COMPLETE || conf_state == 0) {		auth_debug(1, _("krb5 encrypt error to %s: %s\n"),			   rc->hostname, gss_error(maj_stat, min_stat));		return (-1);	    }	    auth_debug(1, _("krb5: k5_encrypt: give %zu bytes\n"),		       enctok.length);	    *encbuf = enctok.value;	    *encbuflen = enctok.length;	} else {	    *encbuf = buf;	    *encbuflen = buflen;	}	auth_debug(1, _("krb5: k5_encrypt: exit\n"));    }    return (0);}static intk5_decrypt(    void *cookie,    void *buf,    ssize_t buflen,    void **decbuf,    ssize_t *decbuflen){    struct tcp_conn *rc = cookie;    gss_buffer_desc enctok;    gss_buffer_desc dectok;    OM_uint32 maj_stat, min_stat;    int conf_state, qop_state;    if (rc->conf_fn && rc->conf_fn("kencrypt", rc->datap)) {	auth_debug(1, _("krb5: k5_decrypt: enter\n"));	if (rc->auth == 1) {	    enctok.length = buflen;	    enctok.value  = buf;    	    auth_debug(1, _("krb5: k5_decrypt: decrypting %zu bytes\n"), enctok.length);	    assert(rc->gss_context != GSS_C_NO_CONTEXT);	    maj_stat = gss_unseal(&min_stat, rc->gss_context, &enctok, &dectok,			      &conf_state, &qop_state);	    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {		auth_debug(1, _("krb5 decrypt error from %s: %s\n"),			   rc->hostname, gss_error(maj_stat, min_stat));		return (-1);	    }	    auth_debug(1, _("krb5: k5_decrypt: give %zu bytes\n"),		       dectok.length);	    *decbuf = dectok.value;	    *decbuflen = dectok.length;	} else {	    *decbuf = buf;	    *decbuflen = buflen;	}	auth_debug(1, _("krb5: k5_decrypt: exit\n"));    } else {	*decbuf = buf;	*decbuflen = buflen;    }    return (0);}/* * check ~/.k5amandahosts to see if this principal is allowed in.  If it's * hardcoded, then we don't check the realm */static char *krb5_checkuser( char *	host,    char *	name,    char *	realm){#ifdef AMANDA_PRINCIPAL    if(strcmp(name, AMANDA_PRINCIPAL) == 0) {	return(NULL);    } else {	return(vstrallocf(_("does not match compiled in default")));    }#else    struct passwd *pwd;    char *ptmp;    char *result = _("generic error");	/* default is to not permit */    FILE *fp = NULL;    struct stat sbuf;    uid_t localuid;    char *line = NULL;    char *filehost = NULL, *fileuser = NULL, *filerealm = NULL;    assert( host != NULL);    assert( name != NULL);    if((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {	result = vstrallocf(_("can not find user %s"), CLIENT_LOGIN);    }    localuid = pwd->pw_uid;#ifdef USE_AMANDAHOSTS    ptmp = stralloc2(pwd->pw_dir, "/.k5amandahosts");#else    ptmp = stralloc2(pwd->pw_dir, "/.k5login");#endif    if(!ptmp) {	result = vstrallocf(_("could not find home directory for %s"), CLIENT_LOGIN);	goto common_exit;   }   /*    * check to see if the ptmp file does nto exist.    */   if(access(ptmp, R_OK) == -1 && errno == ENOENT) {	/*	 * in this case we check to see if the principal matches	 * the destination user mimicing the .k5login functionality.	 */	 if(strcmp(name, CLIENT_LOGIN) != 0) {		result = vstrallocf(_("%s does not match %s"),			name, CLIENT_LOGIN);		return result;	}	result = NULL;	goto common_exit;    }    auth_debug(1, _("opening ptmp: %s\n"), (ptmp)?ptmp: "NULL!");    if((fp = fopen(ptmp, "r")) == NULL) {	result = vstrallocf(_("can not open %s"), ptmp);	return result;    }    auth_debug(1, _("opened ptmp\n"));    if (fstat(fileno(fp), &sbuf) != 0) {	result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));	goto common_exit;    }    if (sbuf.st_uid != localuid) {	result = vstrallocf(_("%s is owned by %ld, should be %ld"),		ptmp, (long)sbuf.st_uid, (long)localuid);	goto common_exit;    }    if ((sbuf.st_mode & 077) != 0) {	result = vstrallocf(	    _("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);	goto common_exit;    }    while ((line = agets(fp)) != NULL) {	if (line[0] == '\0') {	    amfree(line);	    continue;	}	/* if there's more than one column, then it's the host */	if( (filehost = strtok(line, " \t")) == NULL) {	    amfree(line);	    continue;	}	/*	 * if there's only one entry, then it's a username and we have	 * no hostname.  (so the principal is allowed from anywhere.	 */	if((fileuser = strtok(NULL, " \t")) == NULL) {	    fileuser = filehost;	    filehost = NULL;	}	if(filehost && strcmp(filehost, host) != 0) {	    amfree(line);	    continue;	} else {		auth_debug(1, _("found a host match\n"));	}	if( (filerealm = strchr(fileuser, '@')) != NULL) {	    *filerealm++ = '\0';	}	/*	 * we have a match.  We're going to be a little bit insecure	 * and indicate that the principal is correct but the realm is	 * not if that's the case.  Technically we should say nothing	 * and let the user figure it out, but it's helpful for debugging.	 * You likely only get this far if you've turned on cross-realm auth	 * anyway...	 */	auth_debug(1, _("comparing %s %s\n"), fileuser, name);	if(strcmp(fileuser, name) == 0) {		auth_debug(1, _("found a match!\n"));		if(realm && filerealm && (strcmp(realm, filerealm)!=0)) {			amfree(line);			continue;		}		result = NULL;		amfree(line);		goto common_exit;	}	amfree(line);    }    result = vstrallocf(_("no match in %s"), ptmp);common_exit:    afclose(fp);    return(result);#endif /* AMANDA_PRINCIPAL */}

⌨️ 快捷键说明

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