int my_init(void) { PyObject *mainmodule; FILE *f; Py_Initialize (); // fprintf(stderr, "trying to load %s\n", SCRIPT_PATH); f = fopen(SCRIPT_PATH, "r"); if (f == NULL) { if (sctx) krb5_set_error_message(sctx, -1, "couldn't open Python script %s (%s)", SCRIPT_PATH, strerror(errno)); return -1; } set_cloexec_file(f); PyRun_SimpleFile (f, SCRIPT_PATH); fclose(f); mainmodule = PyModule_GetDict(PyImport_AddModule("__main__")); if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; } locatefn = PyDict_GetItemString (mainmodule, LOOKUP_FUNC_NAME); if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; } /* Don't DECREF mainmodule, it's sometimes causing crashes. */ if (locatefn == 0) return -1; if (!PyCallable_Check (locatefn)) { Py_DECREF (locatefn); locatefn = 0; return -1; } if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; } return 0; }
krb5_error_code krb5_ktsrvint_open(krb5_context context, krb5_keytab id) { KTFILEP(id) = fopen(KTFILENAME(id), READ_MODE); if (!KTFILEP(id)) return errno; set_cloexec_file(KTFILEP(id)); return 0; }
/* Open and parse the ACL file. */ static krb5_error_code load_acl_file(krb5_context context, const char *fname, struct acl_state *state) { krb5_error_code ret; FILE *fp; char *line; struct acl_entry **entry_slot; int lineno, incr; state->list = NULL; /* Open the ACL file for reading. */ fp = fopen(fname, "r"); if (fp == NULL) { krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"), error_message(errno), fname); ret = errno; k5_setmsg(context, errno, _("Cannot open %s: %s"), fname, error_message(ret)); return ret; } set_cloexec_file(fp); lineno = 1; incr = 0; entry_slot = &state->list; /* Get a non-comment line. */ while ((line = get_line(fp, fname, &lineno, &incr)) != NULL) { /* Parse it. Fail out on syntax error. */ *entry_slot = parse_line(context, line, fname); if (*entry_slot == NULL) { krb5_klog_syslog(LOG_ERR, _("%s: syntax error at line %d <%.10s...>"), fname, lineno, line); k5_setmsg(context, EINVAL, _("%s: syntax error at line %d <%.10s...>"), fname, lineno, line); free_acl_entries(state); free(line); fclose(fp); return EINVAL; } entry_slot = &(*entry_slot)->next; free(line); } fclose(fp); return 0; }
SETRPCENT_TYPE setrpcent(int f) { register struct rpcdata *d = _rpcdata(); if (d == 0) return; if (d->rpcf == NULL) { d->rpcf = fopen(RPCDB, "r"); if (d->rpcf) set_cloexec_file(d->rpcf); } else rewind(d->rpcf); if (d->current) free(d->current); d->current = NULL; d->stayopen |= f; }
struct rpcent * getrpcent(void) { struct rpcent *hp; int reason; char *key = NULL, *val = NULL; int keylen, vallen; register struct rpcdata *d = _rpcdata(); if (d == 0) return(NULL); if (d->rpcf == NULL) { if ((d->rpcf = fopen(RPCDB, "r")) == NULL) return (NULL); set_cloexec_file(d->rpcf); } if (fgets(d->line, BUFSIZ, d->rpcf) == NULL) return (NULL); return interpret(d->line, strlen(d->line)); }
krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename, int magic) { osa_adb_db_t db; static struct _locklist *locklist = NULL; struct _locklist *lockp; krb5_error_code code; if (dbp == NULL || filename == NULL) return EINVAL; db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent)); if (db == NULL) return ENOMEM; memset(db, 0, sizeof(*db)); db->info.hash = NULL; db->info.bsize = 256; db->info.ffactor = 8; db->info.nelem = 25000; db->info.lorder = 0; db->btinfo.flags = 0; db->btinfo.cachesize = 0; db->btinfo.psize = 4096; db->btinfo.lorder = 0; db->btinfo.minkeypage = 0; db->btinfo.compare = NULL; db->btinfo.prefix = NULL; /* * A process is allowed to open the same database multiple times * and access it via different handles. If the handles use * distinct lockinfo structures, things get confused: lock(A), * lock(B), release(B) will result in the kernel unlocking the * lock file but handle A will still think the file is locked. * Therefore, all handles using the same lock file must share a * single lockinfo structure. * * It is not sufficient to have a single lockinfo structure, * however, because a single process may also wish to open * multiple different databases simultaneously, with different * lock files. This code used to use a single static lockinfo * structure, which means that the second database opened used * the first database's lock file. This was Bad. * * We now maintain a linked list of lockinfo structures, keyed by * lockfilename. An entry is added when this function is called * with a new lockfilename, and all subsequent calls with that * lockfilename use the existing entry, updating the refcnt. * When the database is closed with fini_db(), the refcnt is * decremented, and when it is zero the lockinfo structure is * freed and reset. The entry in the linked list, however, is * never removed; it will just be reinitialized the next time * init_db is called with the right lockfilename. */ /* find or create the lockinfo structure for lockfilename */ lockp = locklist; while (lockp) { if (strcmp(lockp->lockinfo.filename, lockfilename) == 0) break; else lockp = lockp->next; } if (lockp == NULL) { /* doesn't exist, create it, add to list */ lockp = (struct _locklist *) malloc(sizeof(*lockp)); if (lockp == NULL) { free(db); return ENOMEM; } memset(lockp, 0, sizeof(*lockp)); lockp->lockinfo.filename = strdup(lockfilename); if (lockp->lockinfo.filename == NULL) { free(lockp); free(db); return ENOMEM; } lockp->next = locklist; locklist = lockp; } /* now initialize lockp->lockinfo if necessary */ if (lockp->lockinfo.lockfile == NULL) { if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) { free(db); return((krb5_error_code) code); } /* * needs be open read/write so that write locking can work with * POSIX systems */ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) { /* * maybe someone took away write permission so we could only * get shared locks? */ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r")) == NULL) { free(db); return OSA_ADB_NOLOCKFILE; } } set_cloexec_file(lockp->lockinfo.lockfile); lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0; } /* lockp is set, lockinfo is initialized, update the reference count */ db->lock = &lockp->lockinfo; db->lock->refcnt++; db->opencnt = 0; db->filename = strdup(filename); db->magic = magic; *dbp = db; return OSA_ADB_OK; }
krb5_error_code krb5_ldap_readpassword(krb5_context context, krb5_ldap_context *ldap_context, unsigned char **password) { int entryfound=0; krb5_error_code st=0; char line[RECORDLEN]="0", *start=NULL, *file=NULL; char errbuf[1024]; FILE *fptr=NULL; *password = NULL; if (ldap_context->service_password_file) file = ldap_context->service_password_file; #ifndef HAVE_STRERROR_R # undef strerror_r # define strerror_r(ERRNUM, BUF, SIZE) (strncpy(BUF, strerror(ERRNUM), SIZE), BUF[(SIZE)-1] = 0) #endif /* check whether file exists */ if (access(file, F_OK) < 0) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } /* check read access */ if (access(file, R_OK) < 0) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } if ((fptr=fopen(file, "r")) == NULL) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } set_cloexec_file(fptr); /* get the record from the file */ while (fgets(line, RECORDLEN, fptr)!= NULL) { char tmp[RECORDLEN]; tmp[0] = '\0'; /* Handle leading white-spaces */ for (start = line; isspace(*start); ++start); /* Handle comment lines */ if (*start == '!' || *start == '#') continue; sscanf(line, "%*[ \t]%[^#]", tmp); if (tmp[0] == '\0') sscanf(line, "%[^#]", tmp); if (strcasecmp(tmp, ldap_context->bind_dn) == 0) { entryfound = 1; /* service_dn record found !!! */ break; } } fclose (fptr); if (entryfound == 0) { st = KRB5_KDB_SERVER_INTERNAL_ERR; krb5_set_error_message (context, st, "Bind DN entry missing in stash file"); goto rp_exit; } /* replace the \n with \0 */ start = strchr(line, '\n'); if (start) *start = '\0'; start = strchr(line, '#'); if (start == NULL) { /* password field missing */ st = KRB5_KDB_SERVER_INTERNAL_ERR; krb5_set_error_message (context, st, "Stash file entry corrupt"); goto rp_exit; } ++ start; /* Extract the plain password / certificate file information */ { struct data PT, CT; /* Check if the entry has the path of a certificate */ if (!strncmp(start, "{FILE}", strlen("{FILE}"))) { /* Set *password = {FILE}<path to cert>\0<cert password> */ size_t len = strlen(start); *password = (unsigned char *)malloc(len + 2); if (*password == NULL) { st = ENOMEM; goto rp_exit; } memcpy(*password, start, len); (*password)[len] = '\0'; (*password)[len + 1] = '\0'; goto got_password; } else { CT.value = (unsigned char *)start; CT.len = strlen((char *)CT.value); st = dec_password(CT, &PT); if (st != 0) { switch (st) { case ERR_NO_MEM: st = ENOMEM; break; case ERR_PWD_ZERO: st = EINVAL; krb5_set_error_message(context, st, "Password has zero length"); break; case ERR_PWD_BAD: st = EINVAL; krb5_set_error_message(context, st, "Password corrupted"); break; case ERR_PWD_NOT_HEX: st = EINVAL; krb5_set_error_message(context, st, "Not a hexadecimal password"); break; default: st = KRB5_KDB_SERVER_INTERNAL_ERR; break; } goto rp_exit; } *password = PT.value; } } got_password: rp_exit: if (st) { if (*password) free (*password); *password = NULL; } return st; }
static errcode_t write_data_to_file(prf_data_t data, const char *outfile, int can_create) { FILE *f; profile_filespec_t new_file; profile_filespec_t old_file; errcode_t retval = 0; retval = ENOMEM; new_file = old_file = 0; if (asprintf(&new_file, "%s.$$$", outfile) < 0) { new_file = NULL; goto errout; } if (asprintf(&old_file, "%s.bak", outfile) < 0) { old_file = NULL; goto errout; } errno = 0; f = fopen(new_file, "w"); if (!f) { retval = errno; if (retval == 0) retval = PROF_FAIL_OPEN; goto errout; } set_cloexec_file(f); profile_write_tree_file(data->root, f); if (fclose(f) != 0) { retval = errno; goto errout; } unlink(old_file); if (make_hard_link(outfile, old_file) == 0) { /* Okay, got the hard link. Yay. Now we've got our backup version, so just put the new version in place. */ if (rename(new_file, outfile)) { /* Weird, the rename didn't work. But the old version should still be in place, so no special cleanup is needed. */ retval = errno; goto errout; } } else if (errno == ENOENT && can_create) { if (rename(new_file, outfile)) { retval = errno; goto errout; } } else { /* Couldn't make the hard link, so there's going to be a small window where data->filespec does not refer to either version. */ #ifndef _WIN32 sync(); #endif if (rename(outfile, old_file)) { retval = errno; goto errout; } if (rename(new_file, outfile)) { retval = errno; rename(old_file, outfile); /* back out... */ goto errout; } } data->flags = 0; retval = 0; errout: if (new_file) free(new_file); if (old_file) free(old_file); return retval; }
errcode_t profile_update_file_data(prf_data_t data) { errcode_t retval; #ifdef HAVE_STAT struct stat st; unsigned long frac; time_t now; #endif FILE *f; retval = k5_mutex_lock(&data->lock); if (retval) return retval; #ifdef HAVE_STAT now = time(0); if (now == data->last_stat && data->root != NULL) { k5_mutex_unlock(&data->lock); return 0; } if (stat(data->filespec, &st)) { retval = errno; k5_mutex_unlock(&data->lock); return retval; } data->last_stat = now; #if defined HAVE_STRUCT_STAT_ST_MTIMENSEC frac = st.st_mtimensec; #elif defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC frac = st.st_mtimespec.tv_nsec; #elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC frac = st.st_mtim.tv_nsec; #else frac = 0; #endif if (st.st_mtime == data->timestamp && frac == data->frac_ts && data->root != NULL) { k5_mutex_unlock(&data->lock); return 0; } if (data->root) { profile_free_node(data->root); data->root = 0; } if (data->comment) { free(data->comment); data->comment = 0; } #else /* * If we don't have the stat() call, assume that our in-core * memory image is correct. That is, we won't reread the * profile file if it changes. */ if (data->root) { k5_mutex_unlock(&data->lock); return 0; } #endif errno = 0; f = fopen(data->filespec, "r"); if (f == NULL) { retval = errno; k5_mutex_unlock(&data->lock); if (retval == 0) retval = ENOENT; return retval; } set_cloexec_file(f); data->upd_serial++; data->flags &= PROFILE_FILE_SHARED; /* FIXME same as '=' operator */ retval = profile_parse_file(f, &data->root); fclose(f); if (retval) { k5_mutex_unlock(&data->lock); return retval; } assert(data->root != NULL); #ifdef HAVE_STAT data->timestamp = st.st_mtime; data->frac_ts = frac; #endif k5_mutex_unlock(&data->lock); return 0; }
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); }
/* * 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_error_code krb5_ldap_readpassword(krb5_context context, krb5_ldap_context *ldap_context, unsigned char **password) { int entryfound=0; krb5_error_code st=0; char line[RECORDLEN]="0", *start=NULL, *file=NULL; char errbuf[1024]; FILE *fptr=NULL; *password = NULL; if (ldap_context->service_password_file) file = ldap_context->service_password_file; #ifndef HAVE_STRERROR_R # undef strerror_r # define strerror_r(ERRNUM, BUF, SIZE) (strncpy(BUF, strerror(ERRNUM), SIZE), BUF[(SIZE)-1] = 0) #endif /* check whether file exists */ if (access(file, F_OK) < 0) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } /* check read access */ if (access(file, R_OK) < 0) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } if ((fptr=fopen(file, "r")) == NULL) { st = errno; strerror_r(errno, errbuf, sizeof(errbuf)); krb5_set_error_message (context, st, "%s", errbuf); goto rp_exit; } set_cloexec_file(fptr); /* get the record from the file */ while (fgets(line, RECORDLEN, fptr)!= NULL) { char tmp[RECORDLEN]; tmp[0] = '\0'; /* Handle leading white-spaces */ for (start = line; isspace(*start); ++start); /* Handle comment lines */ if (*start == '!' || *start == '#') continue; sscanf(line, "%*[ \t]%[^#]", tmp); if (tmp[0] == '\0') sscanf(line, "%[^#]", tmp); if (strcasecmp(tmp, ldap_context->bind_dn) == 0) { entryfound = 1; /* service_dn record found !!! */ break; } } fclose (fptr); if (entryfound == 0) { st = KRB5_KDB_SERVER_INTERNAL_ERR; krb5_set_error_message(context, st, _("Bind DN entry missing in stash file")); goto rp_exit; } /* replace the \n with \0 */ start = strchr(line, '\n'); if (start) *start = '\0'; start = strchr(line, '#'); if (start == NULL) { /* password field missing */ st = KRB5_KDB_SERVER_INTERNAL_ERR; krb5_set_error_message(context, st, _("Stash file entry corrupt")); goto rp_exit; } ++ start; /* Extract the plain password information. */ st = dec_password(context, start, password); rp_exit: if (st) { if (*password) free (*password); *password = NULL; } return st; }