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;
}