Ejemplo n.º 1
0
static krb5_error_code KRB5_CALLCONV
fkt_add_entry(krb5_context context,
	      krb5_keytab id,
	      krb5_keytab_entry *entry)
{
    int ret;
    int fd;
    krb5_storage *sp;
    struct fkt_data *d = id->data;
    krb5_data keytab;
    int32_t len;

    fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC);
    if (fd < 0) {
	fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600);
	if (fd < 0) {
	    ret = errno;
	    krb5_set_error_message(context, ret,
				   N_("open(%s): %s", ""), d->filename,
				   strerror(ret));
	    return ret;
	}
	rk_cloexec(fd);

	ret = _krb5_xlock(context, fd, 1, d->filename);
	if (ret) {
	    close(fd);
	    return ret;
	}
	sp = krb5_storage_from_fd(fd);
	krb5_storage_set_eof_code(sp, KRB5_KT_END);
	ret = fkt_setup_keytab(context, id, sp);
	if(ret) {
	    goto out;
	}
	storage_set_flags(context, sp, id->version);
    } else {
	int8_t pvno, tag;

	rk_cloexec(fd);

	ret = _krb5_xlock(context, fd, 1, d->filename);
	if (ret) {
	    close(fd);
	    return ret;
	}
	sp = krb5_storage_from_fd(fd);
	krb5_storage_set_eof_code(sp, KRB5_KT_END);
	ret = krb5_ret_int8(sp, &pvno);
	if(ret) {
	    /* we probably have a zero byte file, so try to set it up
               properly */
	    ret = fkt_setup_keytab(context, id, sp);
	    if(ret) {
		krb5_set_error_message(context, ret,
				       N_("%s: keytab is corrupted: %s", ""),
				       d->filename, strerror(ret));
		goto out;
	    }
	    storage_set_flags(context, sp, id->version);
	} else {
	    if(pvno != 5) {
		ret = KRB5_KEYTAB_BADVNO;
		krb5_set_error_message(context, ret,
				       N_("Bad version in keytab %s", ""),
				       d->filename);
		goto out;
	    }
	    ret = krb5_ret_int8 (sp, &tag);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       N_("failed reading tag from "
					  "keytab %s", ""),
				       d->filename);
		goto out;
	    }
	    id->version = tag;
	    storage_set_flags(context, sp, id->version);
	}
    }

    {
	krb5_storage *emem;
	emem = krb5_storage_emem();
	if(emem == NULL) {
	    ret = krb5_enomem(context);
	    goto out;
	}
	ret = krb5_kt_store_principal(context, emem, entry->principal);
	if(ret) {
	    krb5_set_error_message(context, ret,
				   N_("Failed storing principal "
				      "in keytab %s", ""),
				   d->filename);
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_store_int32 (emem, entry->timestamp);
	if(ret) {
	    krb5_set_error_message(context, ret,
				   N_("Failed storing timpstamp "
				      "in keytab %s", ""),
				   d->filename);
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_store_int8 (emem, entry->vno % 256);
	if(ret) {
	    krb5_set_error_message(context, ret,
				   N_("Failed storing kvno "
				      "in keytab %s", ""),
				   d->filename);
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock);
	if(ret) {
	    krb5_storage_free(emem);
	    goto out;
	}
	if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
	    ret = krb5_store_int32 (emem, entry->vno);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       N_("Failed storing extended kvno "
					  "in keytab %s", ""),
				       d->filename);
		krb5_storage_free(emem);
		goto out;
	    }
	    ret = krb5_store_uint32 (emem, entry->flags);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       N_("Failed storing extended kvno "
					  "in keytab %s", ""),
				       d->filename);
		krb5_storage_free(emem);
		goto out;
	    }
	}

	ret = krb5_storage_to_data(emem, &keytab);
	krb5_storage_free(emem);
	if(ret) {
	    krb5_set_error_message(context, ret,
				   N_("Failed converting keytab entry "
				      "to memory block for keytab %s", ""),
				   d->filename);
	    goto out;
	}
    }

    while(1) {
	ret = krb5_ret_int32(sp, &len);
	if(ret == KRB5_KT_END) {
	    len = keytab.length;
	    break;
	}
	if(len < 0) {
	    len = -len;
	    if(len >= (int)keytab.length) {
		krb5_storage_seek(sp, -4, SEEK_CUR);
		break;
	    }
	}
	krb5_storage_seek(sp, len, SEEK_CUR);
    }
    ret = krb5_store_int32(sp, len);
    if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) {
	ret = errno;
	krb5_set_error_message(context, ret,
			       N_("Failed writing keytab block "
				  "in keytab %s: %s", ""),
			       d->filename, strerror(ret));
    }
    memset(keytab.data, 0, keytab.length);
    krb5_data_free(&keytab);
  out:
    krb5_storage_free(sp);
    _krb5_xunlock(context, fd);
    close(fd);
    return ret;
}
Ejemplo n.º 2
0
static krb5_error_code
fkt_add_entry(krb5_context context,
	      krb5_keytab id,
	      krb5_keytab_entry *entry)
{
    int ret;
    int fd;
    krb5_storage *sp;
    struct fkt_data *d = id->data;
    krb5_data keytab;
    int32_t len;
    
    fd = open (d->filename, O_RDWR | O_BINARY);
    if (fd < 0) {
	fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
	if (fd < 0) {
	    ret = errno;
	    krb5_set_error_string(context, "open(%s): %s", d->filename,
				  strerror(ret));
	    return ret;
	}
	ret = _krb5_xlock(context, fd, 1, d->filename);
	if (ret) {
	    close(fd);
	    return ret;
	}
	sp = krb5_storage_from_fd(fd);
	krb5_storage_set_eof_code(sp, KRB5_KT_END);
	ret = fkt_setup_keytab(context, id, sp);
	if(ret) {
	    goto out;
	}
	storage_set_flags(context, sp, id->version);
    } else {
	int8_t pvno, tag;
	ret = _krb5_xlock(context, fd, 1, d->filename);
	if (ret) {
	    close(fd);
	    return ret;
	}
	sp = krb5_storage_from_fd(fd);
	krb5_storage_set_eof_code(sp, KRB5_KT_END);
	ret = krb5_ret_int8(sp, &pvno);
	if(ret) {
	    /* we probably have a zero byte file, so try to set it up
               properly */
	    ret = fkt_setup_keytab(context, id, sp);
	    if(ret) {
		krb5_set_error_string(context, "%s: keytab is corrupted: %s", 
				      d->filename, strerror(ret));
		goto out;
	    }
	    storage_set_flags(context, sp, id->version);
	} else {
	    if(pvno != 5) {
		ret = KRB5_KEYTAB_BADVNO;
		krb5_set_error_string(context, "%s: %s", 
				      d->filename, strerror(ret));
		goto out;
	    }
	    ret = krb5_ret_int8 (sp, &tag);
	    if (ret) {
		krb5_set_error_string(context, "%s: reading tag: %s", 
				      d->filename, strerror(ret));
		goto out;
	    }
	    id->version = tag;
	    storage_set_flags(context, sp, id->version);
	}
    }

    {
	krb5_storage *emem;
	emem = krb5_storage_emem();
	if(emem == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_string (context, "malloc: out of memory");
	    goto out;
	}
	ret = krb5_kt_store_principal(context, emem, entry->principal);
	if(ret) {
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_store_int32 (emem, entry->timestamp);
	if(ret) {
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_store_int8 (emem, entry->vno % 256);
	if(ret) {
	    krb5_storage_free(emem);
	    goto out;
	}
	ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock);
	if(ret) {
	    krb5_storage_free(emem);
	    goto out;
	}
	if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
	    ret = krb5_store_int32 (emem, entry->vno);
	    if (ret) {
		krb5_storage_free(emem);
		goto out;
	    }
	}

	ret = krb5_storage_to_data(emem, &keytab);
	krb5_storage_free(emem);
	if(ret)
	    goto out;
    }
    
    while(1) {
	ret = krb5_ret_int32(sp, &len);
	if(ret == KRB5_KT_END) {
	    len = keytab.length;
	    break;
	}
	if(len < 0) {
	    len = -len;
	    if(len >= keytab.length) {
		krb5_storage_seek(sp, -4, SEEK_CUR);
		break;
	    }
	}
	krb5_storage_seek(sp, len, SEEK_CUR);
    }
    ret = krb5_store_int32(sp, len);
    if(krb5_storage_write(sp, keytab.data, keytab.length) < 0)
	ret = errno;
    memset(keytab.data, 0, keytab.length);
    krb5_data_free(&keytab);
  out:
    krb5_storage_free(sp);
    _krb5_xunlock(context, fd);
    close(fd);
    return ret;
}