From 8681961a7e2f69a98b0e180f96ca135e48ce7e51 Mon Sep 17 00:00:00 2001 From: Richard Basch Date: Fri, 9 Feb 1996 02:19:14 +0000 Subject: [PATCH] * scc.h scc_gprin.c scc_maybe.c scc_skip.c scc_sseq.c Store and retrieve the os_context time offset from the credentials cache. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7465 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/ccache/stdio/scc.h | 10 + src/lib/krb5/ccache/stdio/scc_gprin.c | 6 +- src/lib/krb5/ccache/stdio/scc_maybe.c | 286 ++++++++++++++++---------- src/lib/krb5/ccache/stdio/scc_skip.c | 23 ++- src/lib/krb5/ccache/stdio/scc_sseq.c | 9 +- 5 files changed, 221 insertions(+), 113 deletions(-) diff --git a/src/lib/krb5/ccache/stdio/scc.h b/src/lib/krb5/ccache/stdio/scc.h index aaa75b80a..627eb3adf 100644 --- a/src/lib/krb5/ccache/stdio/scc.h +++ b/src/lib/krb5/ccache/stdio/scc.h @@ -53,6 +53,16 @@ #define SCC_OPEN_RDWR 2 #define SCC_OPEN_RDONLY 3 +/* Credential file header tags. + * The header tags are constructed as: + * krb5_ui_2 tag + * krb5_ui_2 len + * krb5_octet data[len] + * This format allows for older versions of the fcc processing code to skip + * past unrecognized tag formats. + */ +#define SCC_TAG_DELTATIME 1 + #ifndef TKT_ROOT #define TKT_ROOT "/tmp/tkt" #endif diff --git a/src/lib/krb5/ccache/stdio/scc_gprin.c b/src/lib/krb5/ccache/stdio/scc_gprin.c index 3f6c90d5e..5fbc4822d 100644 --- a/src/lib/krb5/ccache/stdio/scc_gprin.c +++ b/src/lib/krb5/ccache/stdio/scc_gprin.c @@ -49,11 +49,13 @@ krb5_scc_get_principal(context, id, princ) krb5_error_code kret; MAYBE_OPEN (context, id, SCC_OPEN_RDONLY); - /* skip over vno at beginning of file */ - fseek(((krb5_scc_data *) id->data)->file, sizeof(krb5_int16), 0); + + kret = krb5_scc_skip_header(context, id); + if (kret) goto done; kret = krb5_scc_read_principal(context, id, princ); +done: MAYBE_CLOSE (context, id, kret); return kret; } diff --git a/src/lib/krb5/ccache/stdio/scc_maybe.c b/src/lib/krb5/ccache/stdio/scc_maybe.c index 2e09b3da6..ebddd0559 100644 --- a/src/lib/krb5/ccache/stdio/scc_maybe.c +++ b/src/lib/krb5/ccache/stdio/scc_maybe.c @@ -70,128 +70,202 @@ krb5_scc_close_file (context, id) krb5_error_code krb5_scc_open_file (context, id, mode) - krb5_context context; + krb5_context context; krb5_ccache id; int mode; { - char fvno_bytes[2]; /* In nework standard byte order, big endian */ - krb5_scc_data *data; - FILE *f; - char *open_flag; - krb5_error_code retval; - - data = (krb5_scc_data *) id->data; - if (data->file) { - /* Don't know what state it's in; shut down and start anew. */ - (void) krb5_unlock_file(context, fileno(data->file)); - (void) fclose (data->file); - data->file = 0; - } + krb5_os_context os_ctx = (krb5_os_context) context->os_context; + krb5_scc_data *data = (krb5_scc_data *) id->data; + char fvno_bytes[2]; /* In nework byte order */ + krb5_ui_2 scc_vno; + krb5_ui_2 scc_tag; + krb5_ui_2 scc_taglen; + krb5_ui_2 scc_hlen; + FILE *f; + char *open_flag; + krb5_error_code retval = 0; + + if (data->file) { + /* Don't know what state it's in; shut down and start anew. */ + (void) krb5_unlock_file(context, fileno(data->file)); + (void) fclose (data->file); + data->file = 0; + } #ifdef ANSI_STDIO - switch(mode) { - case SCC_OPEN_AND_ERASE: - unlink(data->filename); - /* XXX should do an exclusive open here, but no way to do */ - /* this under stdio */ - open_flag = "wb+"; - break; - case SCC_OPEN_RDWR: - open_flag = "rb+"; - break; - case SCC_OPEN_RDONLY: - default: - open_flag = "rb"; - break; - } + switch(mode) { + case SCC_OPEN_AND_ERASE: + unlink(data->filename); + /* XXX should do an exclusive open here, but no way to do */ + /* this under stdio */ + open_flag = "wb+"; + break; + case SCC_OPEN_RDWR: + open_flag = "rb+"; + break; + case SCC_OPEN_RDONLY: + default: + open_flag = "rb"; + break; + } #else - switch(mode) { - case SCC_OPEN_AND_ERASE: - unlink(data->filename); - /* XXX should do an exclusive open here, but no way to do */ - /* this under stdio */ - open_flag = "w+"; - break; - case SCC_OPEN_RDWR: - open_flag = "r+"; - break; - case SCC_OPEN_RDONLY: - default: - open_flag = "r"; - break; - } + switch(mode) { + case SCC_OPEN_AND_ERASE: + unlink(data->filename); + /* XXX should do an exclusive open here, but no way to do */ + /* this under stdio */ + open_flag = "w+"; + break; + case SCC_OPEN_RDWR: + open_flag = "r+"; + break; + case SCC_OPEN_RDONLY: + default: + open_flag = "r"; + break; + } #endif - f = fopen (data->filename, open_flag); - if (!f) - return krb5_scc_interpret (context, errno); + f = fopen (data->filename, open_flag); + if (!f) + return krb5_scc_interpret (context, errno); #ifdef HAS_SETVBUF - setvbuf(f, data->stdio_buffer, _IOFBF, sizeof (data->stdio_buffer)); + setvbuf(f, data->stdio_buffer, _IOFBF, sizeof (data->stdio_buffer)); #else - setbuf (f, data->stdio_buffer); + setbuf (f, data->stdio_buffer); #endif - switch (mode) { - case SCC_OPEN_RDONLY: - if ((retval = krb5_lock_file(context,fileno(f),KRB5_LOCKMODE_SHARED))){ - (void) fclose(f); - return retval; - } - break; - case SCC_OPEN_RDWR: - case SCC_OPEN_AND_ERASE: - if ((retval = krb5_lock_file(context, fileno(f), - KRB5_LOCKMODE_EXCLUSIVE))) { - (void) fclose(f); - return retval; - } - break; - } - if (mode == SCC_OPEN_AND_ERASE) { - /* write the version number */ - int errsave; + switch (mode) { + case SCC_OPEN_RDONLY: + if ((retval = krb5_lock_file(context,fileno(f),KRB5_LOCKMODE_SHARED))){ + (void) fclose(f); + return retval; + } + break; + case SCC_OPEN_RDWR: + case SCC_OPEN_AND_ERASE: + if ((retval = krb5_lock_file(context, fileno(f), + KRB5_LOCKMODE_EXCLUSIVE))) { + (void) fclose(f); + return retval; + } + break; + } + if (mode == SCC_OPEN_AND_ERASE) { + /* write the version number */ + int errsave; + + data->file = f; + data->version = context->scc_default_format; + retval = krb5_scc_store_ui_2(context, id, data->version); + if (retval) goto done; - fvno_bytes[0] = (context->scc_default_format >> 8) & 0xFF; - fvno_bytes[1] = context->scc_default_format & 0xFF; - data->version = context->scc_default_format; - if (!fwrite((char *)fvno_bytes, sizeof(fvno_bytes), 1, f)) { - errsave = errno; - (void) krb5_unlock_file(context, fileno(f)); - (void) fclose(f); - return krb5_scc_interpret(context, errsave); - } - } else { - /* verify a valid version number is there */ - if (!fread((char *)fvno_bytes, sizeof(fvno_bytes), 1, f)) { - (void) krb5_unlock_file(context, fileno(f)); - (void) fclose(f); - return KRB5_CC_FORMAT; - } - data->version = (fvno_bytes[0] << 8) + fvno_bytes[1]; - if ((data->version != KRB5_SCC_FVNO_1) && - (data->version != KRB5_SCC_FVNO_2) && - (data->version != KRB5_SCC_FVNO_3) && - (data->version != KRB5_SCC_FVNO_4)) { - (void) krb5_unlock_file(context, fileno(f)); - (void) fclose(f); - return KRB5_CCACHE_BADVNO; - } if (data->version == KRB5_SCC_FVNO_4) { - char buf[1024]; - int len; + scc_hlen = 0; + + if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) + scc_hlen += (2*sizeof(krb5_ui_2) + 2*sizeof(krb5_int32)); + + /* Write header length */ + retval = krb5_scc_store_ui_2(context, id, (krb5_int32)scc_hlen); + if (retval) goto done; + + if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { + /* Write time offset tag */ + scc_tag = SCC_TAG_DELTATIME; + scc_taglen = 2*sizeof(krb5_int32); + + retval = krb5_scc_store_ui_2(context,id,(krb5_int32)scc_tag); + if (retval) goto done; + retval = krb5_scc_store_ui_2(context,id,(krb5_int32)scc_taglen); + if (retval) goto done; + retval = krb5_scc_store_int32(context,id,os_ctx->time_offset); + if (retval) goto done; + retval = krb5_scc_store_int32(context,id,os_ctx->usec_offset); + if (retval) goto done; + } + } + goto done; + } + + /* verify a valid version number is there */ + if (!fread((char *)fvno_bytes, sizeof(fvno_bytes), 1, f)) + { + retval = KRB5_CC_FORMAT; + goto done; + } + data->version = (fvno_bytes[0] << 8) + fvno_bytes[1]; + if ((data->version != KRB5_SCC_FVNO_1) && + (data->version != KRB5_SCC_FVNO_2) && + (data->version != KRB5_SCC_FVNO_3) && + (data->version != KRB5_SCC_FVNO_4)) + { + retval = KRB5_CCACHE_BADVNO; + goto done; + } + + data->file = f; + + if (data->version == KRB5_SCC_FVNO_4) { + char buf[1024]; - if (!fread((char *)fvno_bytes, sizeof(fvno_bytes), 1, f)) { - (void) krb5_unlock_file(context, fileno(f)); - (void) fclose(f); - return KRB5_CC_FORMAT; + if (krb5_scc_read_ui_2(context, id, &scc_hlen) || + (scc_hlen > sizeof(buf))) + { + retval = KRB5_CC_FORMAT; + goto done; + } + + while (scc_hlen) { + if ((scc_hlen < (2*sizeof(krb5_ui_2))) || + krb5_scc_read_ui_2(context, id, &scc_tag) || + krb5_scc_read_ui_2(context, id, &scc_taglen) || + (scc_taglen > (scc_hlen - 2*sizeof(krb5_ui_2)))) + { + retval = KRB5_CC_FORMAT; + goto done; } - if ((len = (fvno_bytes[0] << 8) + fvno_bytes[1]) != 0) { - if (!fread(buf, len, 1, f)) { - (void) krb5_unlock_file(context, fileno(f)); - (void) fclose(f); - return KRB5_CC_FORMAT; + + switch (scc_tag) { + case SCC_TAG_DELTATIME: + if (scc_taglen != 2*sizeof(krb5_int32)) { + retval = KRB5_CC_FORMAT; + goto done; } + if (!(context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) || + (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) + { + if (krb5_scc_read(context, id, buf, scc_taglen)) { + retval = KRB5_CC_FORMAT; + goto done; + } + break; + } + if (krb5_scc_read_int32(context, id, &os_ctx->time_offset) || + krb5_scc_read_int32(context, id, &os_ctx->usec_offset)) + { + retval = KRB5_CC_FORMAT; + goto done; + } + os_ctx->os_flags = + ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | + KRB5_OS_TOFFSET_VALID); + break; + default: + if (scc_taglen && krb5_scc_read(context,id,buf,scc_taglen)) { + retval = KRB5_CC_FORMAT; + goto done; + } + break; } + scc_hlen -= (2*sizeof(krb5_ui_2) + scc_taglen); } } - data->file = f; - return 0; + +done: + if (retval) + if (f) { + data->file = 0; + (void) krb5_unlock_file(context, fileno(f)); + (void) fclose(f); + } + return retval; } diff --git a/src/lib/krb5/ccache/stdio/scc_skip.c b/src/lib/krb5/ccache/stdio/scc_skip.c index 01824026f..6b072dc5e 100644 --- a/src/lib/krb5/ccache/stdio/scc_skip.c +++ b/src/lib/krb5/ccache/stdio/scc_skip.c @@ -28,6 +28,27 @@ #include "scc.h" +krb5_error_code +krb5_scc_skip_header(context, id) + krb5_context context; + krb5_ccache id; +{ + krb5_error_code kret; + krb5_principal princ; + krb5_scc_data *data = (krb5_scc_data *) id->data; + krb5_ui_2 scc_flen; + + if (fseek(data->file, sizeof(krb5_ui_2), SEEK_SET)) + return errno; + if (data->version == KRB5_SCC_FVNO_4) { + kret = krb5_scc_read_ui_2(context, id, &scc_flen); + if (kret) return kret; + if (fseek(data->file, scc_flen, SEEK_CUR)) + return errno; + } + return KRB5_OK; +} + krb5_error_code krb5_scc_skip_principal(context, id) krb5_context context; @@ -43,5 +64,3 @@ krb5_scc_skip_principal(context, id) krb5_free_principal(context, princ); return KRB5_OK; } - - diff --git a/src/lib/krb5/ccache/stdio/scc_sseq.c b/src/lib/krb5/ccache/stdio/scc_sseq.c index f1971c5d2..c5bac1967 100644 --- a/src/lib/krb5/ccache/stdio/scc_sseq.c +++ b/src/lib/krb5/ccache/stdio/scc_sseq.c @@ -56,13 +56,16 @@ krb5_scc_start_seq_get(context, id, cursor) /* Make sure we start reading right after the primary principal */ MAYBE_OPEN (context, id, SCC_OPEN_RDONLY); - /* skip over vno at beginning of file */ - fseek(((krb5_scc_data *) id->data)->file, sizeof(krb5_int16), 0); - krb5_scc_skip_principal(context, id); + ret = krb5_scc_skip_header(context, id); + if (ret) goto done; + ret = krb5_scc_skip_principal(context, id); + if (ret) goto done; + fcursor->pos = ftell(((krb5_scc_data *) id->data)->file); *cursor = (krb5_cc_cursor) fcursor; +done: MAYBE_CLOSE (context, id, ret); return(ret); } -- 2.26.2