OM_uint32 KRB5_CALLCONV gss_pname_to_uid(OM_uint32 *minor, const gss_name_t name, const gss_OID mech_type, uid_t *uidOut) { OM_uint32 major = GSS_S_UNAVAILABLE, tmpminor; #ifndef NO_PASSWORD gss_buffer_desc localname; char pwbuf[BUFSIZ]; char *localuser = NULL; struct passwd *pwd = NULL; struct passwd pw; int code = 0; localname.value = NULL; major = gss_localname(minor, name, mech_type, &localname); if (!GSS_ERROR(major) && localname.value) { localuser = malloc(localname.length + 1); if (localuser == NULL) code = ENOMEM; if (code == 0) { memcpy(localuser, localname.value, localname.length); localuser[localname.length] = '\0'; code = k5_getpwnam_r(localuser, &pw, pwbuf, sizeof(pwbuf), &pwd); } if ((code == 0) && pwd) *uidOut = pwd->pw_uid; else major = GSS_S_FAILURE; } free(localuser); if (localname.value) gss_release_buffer(&tmpminor, &localname); #endif /*NO_PASSWORD*/ return major; }
/* * Determine whether principal is authorized to log in as luser according to * the user's k5login file. Return ACCEPT if the k5login file authorizes the * principal, PASS if the k5login file does not exist, or REJECT if the k5login * file exists but does not authorize the principal. If k5login files are * configured to be non-authoritative, pass instead of rejecting. */ static enum result k5login_ok(krb5_context context, krb5_principal principal, const char *luser) { int authoritative = TRUE, gobble; enum result result = REJECT; char *filename = NULL, *princname = NULL; char *newline, linebuf[BUFSIZ], pwbuf[BUFSIZ]; struct stat sbuf; struct passwd pwx, *pwd; FILE *fp = NULL; if (profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS, KRB5_CONF_K5LOGIN_AUTHORITATIVE, NULL, TRUE, &authoritative) != 0) goto cleanup; /* Get the local user's homedir and uid. */ if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0) goto cleanup; if (get_k5login_filename(context, luser, pwd->pw_dir, &filename) != 0) goto cleanup; if (access(filename, F_OK) != 0) { result = PASS; goto cleanup; } if (krb5_unparse_name(context, principal, &princname) != 0) goto cleanup; fp = fopen(filename, "r"); if (fp == NULL) goto cleanup; set_cloexec_file(fp); /* For security reasons, the .k5login file must be owned either by * the user or by root. */ if (fstat(fileno(fp), &sbuf)) goto cleanup; if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) goto cleanup; /* Check each line. */ while (result != ACCEPT && (fgets(linebuf, sizeof(linebuf), fp) != NULL)) { newline = strrchr(linebuf, '\n'); if (newline != NULL) *newline = '\0'; if (strcmp(linebuf, princname) == 0) result = ACCEPT; /* Clean up the rest of the line if necessary. */ if (newline == NULL) while (((gobble = getc(fp)) != EOF) && gobble != '\n'); } cleanup: free(princname); free(filename); if (fp != NULL) fclose(fp); /* If k5login files are non-authoritative, never reject. */ return (!authoritative && result == REJECT) ? PASS : result; }
krb5_boolean KRB5_CALLCONV krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser) { struct stat sbuf; struct passwd *pwd; char pbuf[MAXPATHLEN]; krb5_boolean isok = FALSE; FILE *fp; char kuser[MAX_USERNAME]; char *princname; char linebuf[BUFSIZ]; char *newline; int gobble; /* no account => no access */ char pwbuf[BUFSIZ]; struct passwd pwx; if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0) return(FALSE); (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1); pbuf[sizeof(pbuf) - 1] = '\0'; (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf)); if (access(pbuf, F_OK)) { /* not accessible */ /* * if he's trying to log in as himself, and there is no .k5login file, * let him. To find out, call * krb5_aname_to_localname to convert the principal to a name * which we can string compare. */ if (!(krb5_aname_to_localname(context, principal, sizeof(kuser), kuser)) && (strcmp(kuser, luser) == 0)) { return(TRUE); } } if (krb5_unparse_name(context, principal, &princname)) return(FALSE); /* no hope of matching */ /* open ~/.k5login */ if ((fp = fopen(pbuf, "r")) == NULL) { free(princname); return(FALSE); } set_cloexec_file(fp); /* * For security reasons, the .k5login file must be owned either by * the user himself, or by root. Otherwise, don't grant access. */ if (fstat(fileno(fp), &sbuf)) { fclose(fp); free(princname); return(FALSE); } if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) { fclose(fp); free(princname); return(FALSE); } /* check each line */ while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) { /* null-terminate the input string */ linebuf[BUFSIZ-1] = '\0'; newline = NULL; /* nuke the newline if it exists */ if ((newline = strchr(linebuf, '\n'))) *newline = '\0'; if (!strcmp(linebuf, princname)) { isok = TRUE; continue; } /* clean up the rest of the line if necessary */ if (!newline) while (((gobble = getc(fp)) != EOF) && gobble != '\n'); } free(princname); fclose(fp); return(isok); }
static OM_uint32 attr_pname_to_uid(OM_uint32 *minor, const gss_mechanism mech, const gss_name_t mech_name, uid_t *uidp) { OM_uint32 major = GSS_S_UNAVAILABLE; #ifndef NO_PASSWORD OM_uint32 tmpMinor; int more = -1; if (mech->gss_get_name_attribute == NULL) return GSS_S_UNAVAILABLE; while (more != 0) { gss_buffer_desc value; gss_buffer_desc display_value; int authenticated = 0, complete = 0, code; char pwbuf[BUFSIZ]; struct passwd pw, *pwd; char *localLoginUser; major = mech->gss_get_name_attribute(minor, mech_name, GSS_C_ATTR_LOCAL_LOGIN_USER, &authenticated, &complete, &value, &display_value, &more); if (GSS_ERROR(major)) { map_error(minor, mech); break; } localLoginUser = malloc(value.length + 1); if (localLoginUser == NULL) { major = GSS_S_FAILURE; *minor = ENOMEM; break; } memcpy(localLoginUser, value.value, value.length); localLoginUser[value.length] = '\0'; code = k5_getpwnam_r(localLoginUser, &pw, pwbuf, sizeof(pwbuf), &pwd); free(localLoginUser); gss_release_buffer(&tmpMinor, &value); gss_release_buffer(&tmpMinor, &display_value); if (code == 0 && pwd != NULL) { *uidp = pwd->pw_uid; major = GSS_S_COMPLETE; *minor = 0; break; } else major = GSS_S_UNAVAILABLE; } #endif /* !NO_PASSWORD */ return major; }