📄 tf_util.c
字号:
/* * $Source: /usr/src/kerberosIV/krb/RCS/tf_util.c,v $ * $Author: bostic $ * * Copyright 1987, 1988 by the Massachusetts Institute of Technology. * * For copying and distribution information, please see the file * <mit-copyright.h>. */#ifndef lintstatic char rcsid_tf_util_c[] ="$Id: tf_util.c,v 4.10 93/05/21 17:45:38 bostic Exp $";#endif /* lint */#include <mit-copyright.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <des.h>#include <krb.h>#ifdef TKT_SHMEM#include <sys/param.h>#include <sys/ipc.h>#include <sys/shm.h>#endif /* TKT_SHMEM */#define TOO_BIG -1#define TF_LCK_RETRY ((unsigned)2) /* seconds to sleep before * retry if ticket file is * locked */extern errno;extern int krb_debug;#ifdef TKT_SHMEMchar *krb_shm_addr = 0;static char *tmp_shm_addr = 0;static char krb_dummy_skey[8] = {0,0,0,0,0,0,0,0};char *shmat();#endif /* TKT_SHMEM *//* * fd must be initialized to something that won't ever occur as a real * file descriptor. Since open(2) returns only non-negative numbers as * valid file descriptors, and tf_init always stuffs the return value * from open in here even if it is an error flag, we must * a. Initialize fd to a negative number, to indicate that it is * not initially valid. * b. When checking for a valid fd, assume that negative values * are invalid (ie. when deciding whether tf_init has been * called.) * c. In tf_close, be sure it gets reinitialized to a negative * number. */static fd = -1;static curpos; /* Position in tfbfr */static lastpos; /* End of tfbfr */static char tfbfr[BUFSIZ]; /* Buffer for ticket data */static tf_gets(), tf_read();/* * This file contains routines for manipulating the ticket cache file. * * The ticket file is in the following format: * * principal's name (null-terminated string) * principal's instance (null-terminated string) * CREDENTIAL_1 * CREDENTIAL_2 * ... * CREDENTIAL_n * EOF * * Where "CREDENTIAL_x" consists of the following fixed-length * fields from the CREDENTIALS structure (see "krb.h"): * * char service[ANAME_SZ] * char instance[INST_SZ] * char realm[REALM_SZ] * C_Block session * int lifetime * int kvno * KTEXT_ST ticket_st * long issue_date * * Short description of routines: * * tf_init() opens the ticket file and locks it. * * tf_get_pname() returns the principal's name. * * tf_get_pinst() returns the principal's instance (may be null). * * tf_get_cred() returns the next CREDENTIALS record. * * tf_save_cred() appends a new CREDENTIAL record to the ticket file. * * tf_close() closes the ticket file and releases the lock. * * tf_gets() returns the next null-terminated string. It's an internal * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred(). * * tf_read() reads a given number of bytes. It's an internal routine * used by tf_get_cred(). *//* * tf_init() should be called before the other ticket file routines. * It takes the name of the ticket file to use, "tf_name", and a * read/write flag "rw" as arguments. * * It tries to open the ticket file, checks the mode, and if everything * is okay, locks the file. If it's opened for reading, the lock is * shared. If it's opened for writing, the lock is exclusive. * * Returns KSUCCESS if all went well, otherwise one of the following: * * NO_TKT_FIL - file wasn't there * TKT_FIL_ACC - file was in wrong mode, etc. * TKT_FIL_LCK - couldn't lock the file, even after a retry */tf_init(tf_name, rw) char *tf_name;{ int wflag; uid_t me, getuid(); struct stat stat_buf;#ifdef TKT_SHMEM char shmidname[MAXPATHLEN]; FILE *sfp; int shmid;#endif switch (rw) { case R_TKT_FIL: wflag = 0; break; case W_TKT_FIL: wflag = 1; break; default: if (krb_debug) fprintf(stderr, "tf_init: illegal parameter\n"); return TKT_FIL_ACC; } if (lstat(tf_name, &stat_buf) < 0) switch (errno) { case ENOENT: return NO_TKT_FIL; default: return TKT_FIL_ACC; } me = getuid(); if ((stat_buf.st_uid != me && me != 0) || ((stat_buf.st_mode & S_IFMT) != S_IFREG)) return TKT_FIL_ACC;#ifdef TKT_SHMEM (void) strcpy(shmidname, tf_name); (void) strcat(shmidname, ".shm"); if (stat(shmidname,&stat_buf) < 0) return(TKT_FIL_ACC); if ((stat_buf.st_uid != me && me != 0) || ((stat_buf.st_mode & S_IFMT) != S_IFREG)) return TKT_FIL_ACC;#endif /* TKT_SHMEM */ /* * If "wflag" is set, open the ticket file in append-writeonly mode * and lock the ticket file in exclusive mode. If unable to lock * the file, sleep and try again. If we fail again, return with the * proper error message. */ curpos = sizeof(tfbfr);#ifdef TKT_SHMEM sfp = fopen(shmidname, "r"); /* only need read/write on the actual tickets */ if (sfp == 0) return TKT_FIL_ACC; shmid = -1; { char buf[BUFSIZ]; int val; /* useful for debugging fscanf */ /* We provide our own buffer here since some STDIO libraries barf on unbuffered input with fscanf() */ setbuf(sfp, buf); if ((val = fscanf(sfp,"%d",&shmid)) != 1) { (void) fclose(sfp); return TKT_FIL_ACC; } if (shmid < 0) { (void) fclose(sfp); return TKT_FIL_ACC; } (void) fclose(sfp); } /* * global krb_shm_addr is initialized to 0. Ultrix bombs when you try and * attach the same segment twice so we need this check. */ if (!krb_shm_addr) { if ((krb_shm_addr = shmat(shmid,0,0)) == -1){ if (krb_debug) fprintf(stderr, "cannot attach shared memory for segment %d\n", shmid); krb_shm_addr = 0; /* reset so we catch further errors */ return TKT_FIL_ACC; } } tmp_shm_addr = krb_shm_addr;#endif /* TKT_SHMEM */ if (wflag) { fd = open(tf_name, O_RDWR, 0600); if (fd < 0) { return TKT_FIL_ACC; } if (flock(fd, LOCK_EX | LOCK_NB) < 0) { sleep(TF_LCK_RETRY); if (flock(fd, LOCK_EX | LOCK_NB) < 0) { (void) close(fd); fd = -1; return TKT_FIL_LCK; } } return KSUCCESS; } /* * Otherwise "wflag" is not set and the ticket file should be opened * for read-only operations and locked for shared access. */ fd = open(tf_name, O_RDONLY, 0600); if (fd < 0) { return TKT_FIL_ACC; } if (flock(fd, LOCK_SH | LOCK_NB) < 0) { sleep(TF_LCK_RETRY); if (flock(fd, LOCK_SH | LOCK_NB) < 0) { (void) close(fd); fd = -1; return TKT_FIL_LCK; } } return KSUCCESS;}/* * tf_get_pname() reads the principal's name from the ticket file. It * should only be called after tf_init() has been called. The * principal's name is filled into the "p" parameter. If all goes well, * KSUCCESS is returned. If tf_init() wasn't called, TKT_FIL_INI is * returned. If the name was null, or EOF was encountered, or the name * was longer than ANAME_SZ, TKT_FIL_FMT is returned. */tf_get_pname(p) char *p;{ if (fd < 0) { if (krb_debug) fprintf(stderr, "tf_get_pname called before tf_init.\n"); return TKT_FIL_INI; } if (tf_gets(p, ANAME_SZ) < 2) /* can't be just a null */ return TKT_FIL_FMT; return KSUCCESS;}/* * tf_get_pinst() reads the principal's instance from a ticket file. * It should only be called after tf_init() and tf_get_pname() have been * called. The instance is filled into the "inst" parameter. If all * goes well, KSUCCESS is returned. If tf_init() wasn't called, * TKT_FIL_INI is returned. If EOF was encountered, or the instance * was longer than ANAME_SZ, TKT_FIL_FMT is returned. Note that the * instance may be null. */tf_get_pinst(inst)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -