📄 krb5-security.c
字号:
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 + -