KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_tkt_creds_step(krb5_context context, krb5_tkt_creds_context ctx, krb5_data *in, krb5_data *out, krb5_realm *realm, unsigned int *flags) { krb5_error_code ret; krb5_data_zero(out); *flags = 0; *realm = NULL; ret = ctx->error = 0; while (out->length == 0 && ctx->state != NULL) { ret = ctx->state(context, ctx, in, out, realm, flags); if (ret) { heim_assert(ctx->error == ret, "error not same as saved"); break; } if ((*flags) & KRB5_TKT_STATE_CONTINUE) { heim_assert(out->length != 0, "no data to send to KDC"); heim_assert(*realm != NULL, "no realm to send data too"); break; } else { heim_assert(out->length == 0, "out state but not state continue"); } } return ret; }
/** * Delete a key and its value from the DB * * * @param db Open DB handle * @param key Key * @param error Output error object * * @return 0 on success, system error otherwise * * @addtogroup heimbase */ int heim_db_delete_key(heim_db_t db, heim_string_t table, heim_data_t key, heim_error_t *error) { heim_string_t key64 = NULL; int ret; if (error != NULL) *error = NULL; if (table == NULL) table = HSTR(""); if (heim_get_tid(db) != HEIM_TID_DB) return EINVAL; if (db->plug->delf == NULL) return EBADF; if (!db->in_transaction) { ret = heim_db_begin(db, 0, error); if (ret) goto err; heim_assert(db->in_transaction, "Internal error"); ret = heim_db_delete_key(db, table, key, error); if (ret) { (void) heim_db_rollback(db, NULL); return ret; } return heim_db_commit(db, error); } /* Transaction emulation */ heim_assert(db->set_keys != NULL, "Internal error"); key64 = to_base64(key, error); if (key64 == NULL) return HEIM_ENOMEM(error); if (db->ro_tx) { ret = heim_db_begin(db, 0, error); if (ret) goto err; } ret = heim_path_create(db->del_keys, 29, heim_number_create(1), error, table, key64, NULL); if (ret) goto err; heim_path_delete(db->set_keys, error, table, key64, NULL); heim_release(key64); return 0; err: heim_release(key64); return HEIM_ERROR(error, ret, (ret, N_("Could not set a dict value while while " "deleting a DB value", ""))); }
static int db_replay_log(heim_db_t db, heim_error_t *error) { int ret; heim_string_t journal_fname = NULL; heim_object_t journal; size_t len; heim_assert(!db->in_transaction, "DB transaction not open"); heim_assert(db->set_keys == NULL && db->set_keys == NULL, "DB transaction not open"); if (error) *error = NULL; if (db->options == NULL) return 0; journal_fname = heim_dict_get_value(db->options, HSTR("journal-filename")); if (journal_fname == NULL) return 0; ret = read_json(heim_string_get_utf8(journal_fname), &journal, error); if (ret == ENOENT) return 0; if (ret == 0 && journal == NULL) return 0; if (ret != 0) return ret; if (heim_get_tid(journal) != HEIM_TID_ARRAY) return HEIM_ERROR(error, EINVAL, (ret, N_("Invalid journal contents; delete journal", ""))); len = heim_array_get_length(journal); if (len > 0) db->set_keys = heim_array_get_value(journal, 0); if (len > 1) db->del_keys = heim_array_get_value(journal, 1); ret = db_do_log_actions(db, error); if (ret) return ret; /* Truncate replay log and we're done */ ret = open_file(heim_string_get_utf8(journal_fname), 1, 0, NULL, error); if (ret) return ret; heim_release(db->set_keys); heim_release(db->del_keys); db->set_keys = NULL; db->del_keys = NULL; return 0; }
static krb5_error_code fast_add_cookie(kdc_request_t r, METHOD_DATA *method_data) { krb5_crypto crypto = NULL; KDCFastCookie shell; krb5_error_code ret; krb5_data data; size_t size; memset(&shell, 0, sizeof(shell)); r->fast.expiration = kdc_time + FAST_EXPIRATION_TIME; ASN1_MALLOC_ENCODE(KDCFastState, data.data, data.length, &r->fast, &size, ret); if (ret) return ret; heim_assert(size == data.length, "internal asn1 encoder error"); ret = get_fastuser_crypto(r, KRB5_ENCTYPE_NULL, &crypto); if (ret) goto out; ret = krb5_encrypt_EncryptedData(r->context, crypto, KRB5_KU_H5L_COOKIE, data.data, data.length, 0, &shell.cookie); krb5_crypto_destroy(r->context, crypto); if (ret) goto out; free(data.data); shell.version = "H5L1"; ASN1_MALLOC_ENCODE(KDCFastCookie, data.data, data.length, &shell, &size, ret); free_EncryptedData(&shell.cookie); if (ret) goto out; heim_assert(size == data.length, "internal asn1 encoder error"); ret = krb5_padata_add(r->context, method_data, KRB5_PADATA_FX_COOKIE, data.data, data.length); out: if (ret) free(data.data); return ret; }
static krb5_error_code KRB5_CALLCONV xcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) { CFDictionaryRef query; struct xcc_cursor *c; const void *keys[] = { (void *)kHEIMAttrType, (void *)kHEIMAttrServerName, }; const void *values[] = { (void *)kHEIMTypeKerberos, (void *)kCFNull, }; c = calloc(1, sizeof(*c)); if (c == NULL) return krb5_enomem(context); query = CFDictionaryCreate(NULL, keys, values, sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); heim_assert(query != NULL, "Failed to create dictionary"); c->array = HeimCredCopyQuery(query); CFRELEASE_NULL(query); if (c->array == NULL) { free_cursor(c); return KRB5_CC_END; } *cursor = c; return 0; }
static krb5_error_code KRB5_CALLCONV xcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags which, krb5_creds *cred) { CFDictionaryRef query; krb5_xcc *x = XCACHE(id); CFStringRef servername = CFStringCreateFromPrincipal(context, cred->server); if (servername == NULL) return KRB5_CC_END; const void *keys[] = { (void *)kHEIMAttrParentCredential, kHEIMAttrType, kHEIMAttrServerName }; const void *values[] = { (void *)x->uuid, kHEIMTypeKerberos, servername }; /* XXX match enctype */ query = CFDictionaryCreate(NULL, keys, values, sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); heim_assert(query != NULL, "Failed to create dictionary"); CFRELEASE_NULL(servername); bool res = HeimCredDeleteQuery(query, NULL); CFRELEASE_NULL(query); if (!res) { krb5_set_error_message(context, KRB5_CC_NOTFOUND, N_("Deleted credential not found", "")); return KRB5_CC_NOTFOUND; } return 0; }
static krb5_error_code KRB5_CALLCONV xcc_get_first (krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) { CFDictionaryRef query; krb5_xcc *x = XCACHE(id); CFUUIDRef uuid = HeimCredGetUUID(x->cred); struct xcc_cursor *c; c = calloc(1, sizeof(*c)); if (c == NULL) return krb5_enomem(context); const void *keys[] = { (void *)kHEIMAttrParentCredential, kHEIMAttrType }; const void *values[] = { (void *)uuid, kHEIMTypeKerberos }; query = CFDictionaryCreate(NULL, keys, values, sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); heim_assert(query != NULL, "out of memory"); c->array = HeimCredCopyQuery(query); CFRELEASE_NULL(query); if (c->array == NULL) { free_cursor(c); return KRB5_CC_END; } *cursor = c; return 0; }
static void scram_data_alloc(heim_scram_data *to, size_t length) { to->length = length; to->data = malloc(to->length); heim_assert(to->data != NULL, "out of memory"); }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_default_in_tkt_etypes(krb5_context context, krb5_pdu pdu_type, krb5_enctype **etypes) { krb5_enctype *enctypes = NULL; krb5_error_code ret; krb5_enctype *p; heim_assert(pdu_type == KRB5_PDU_AS_REQUEST || pdu_type == KRB5_PDU_TGS_REQUEST || pdu_type == KRB5_PDU_NONE, "pdu contant not as expected"); if (pdu_type == KRB5_PDU_AS_REQUEST && context->as_etypes != NULL) enctypes = context->as_etypes; else if (pdu_type == KRB5_PDU_TGS_REQUEST && context->tgs_etypes != NULL) enctypes = context->tgs_etypes; else if (context->etypes != NULL) enctypes = context->etypes; if (enctypes != NULL) { ret = copy_enctypes(context, enctypes, &p); if (ret) return ret; } else { ret = default_etypes(context, &p); if (ret) return ret; } *etypes = p; return 0; }
/** heim_db_register * @brief Registers a DB type for use with heim_db_create(). * * @param dbtype Name of DB type * @param data Private data argument to the dbtype's openf method * @param plugin Structure with DB type methods (function pointers) * * Backends that provide begin/commit/rollback methods must provide ACID * semantics. * * The registered DB type will have ACID semantics for backends that do * not provide begin/commit/rollback methods but do provide lock/unlock * and rdjournal/wrjournal methods (using a replay log journalling * scheme). * * If the registered DB type does not natively provide read vs. write * transaction isolation but does provide a lock method then the DB will * provide read/write transaction isolation. * * @return ENOMEM on failure, else 0. * * @addtogroup heimbase */ int heim_db_register(const char *dbtype, void *data, struct heim_db_type *plugin) { heim_dict_t plugins; heim_string_t s; db_plugin plug, plug2; int ret = 0; if ((plugin->beginf != NULL && plugin->commitf == NULL) || (plugin->beginf != NULL && plugin->rollbackf == NULL) || (plugin->lockf != NULL && plugin->unlockf == NULL) || plugin->copyf == NULL) heim_abort("Invalid DB plugin; make sure methods are paired"); /* Initialize */ plugins = heim_dict_create(11); if (plugins == NULL) return ENOMEM; heim_base_once_f(&db_plugin_init_once, plugins, db_init_plugins_once); heim_release(plugins); heim_assert(db_plugins != NULL, "heim_db plugin table initialized"); s = heim_string_create(dbtype); if (s == NULL) return ENOMEM; plug = heim_alloc(sizeof (*plug), "db_plug", plugin_dealloc); if (plug == NULL) { heim_release(s); return ENOMEM; } plug->name = heim_retain(s); plug->openf = plugin->openf; plug->clonef = plugin->clonef; plug->closef = plugin->closef; plug->lockf = plugin->lockf; plug->unlockf = plugin->unlockf; plug->syncf = plugin->syncf; plug->beginf = plugin->beginf; plug->commitf = plugin->commitf; plug->rollbackf = plugin->rollbackf; plug->copyf = plugin->copyf; plug->setf = plugin->setf; plug->delf = plugin->delf; plug->iterf = plugin->iterf; plug->data = data; HEIMDAL_MUTEX_lock(&db_type_mutex); plug2 = heim_dict_get_value(db_plugins, s); if (plug2 == NULL) ret = heim_dict_set_value(db_plugins, s, plug); HEIMDAL_MUTEX_unlock(&db_type_mutex); heim_release(plug); heim_release(s); return ret; }
static void init_string(void *ptr) { heim_dict_t *dict = ptr; *dict = heim_dict_create(101); heim_assert(*dict != NULL, "__heim_string_constant"); }
static void eval_object(heim_object_t o) { heim_tid_t t = heim_get_tid(o); if (t == heim_array_get_type_id()) { heim_array_iterate_f(o, NULL, eval_array_element); } else if (t == heim_dict_get_type_id()) { const char *op = heim_dict_get_value(o, HSTR("op")); heim_assert(op != NULL, "op missing"); if (strcmp(op, "repeat") == 0) { eval_repeat(o); } else if (strcmp(op, "kinit") == 0) { eval_kinit(o); } else if (strcmp(op, "kgetcred") == 0) { eval_kgetcred(o); } else if (strcmp(op, "kdestroy") == 0) { eval_kdestroy(o); } else { errx(1, "unsupported ops %s", op); } } else errx(1, "unsupported"); }
static kadm5_ret_t kadm5_s_lock(void *server_handle) { kadm5_server_context *context = server_handle; kadm5_ret_t ret; if (context->keep_open) { /* * We open/close around every operation, but we retain the DB * open if the DB was locked with a prior call to kadm5_lock(), * so if it's open here that must be because the DB is locked. */ heim_assert(context->db->lock_count > 0, "Internal error in tracking HDB locks"); return KADM5_ALREADY_LOCKED; } ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); if (ret) return ret; ret = context->db->hdb_lock(context->context, context->db, HDB_WLOCK); if (ret) return ret; context->keep_open = 1; return 0; }
static krb5_error_code SP_HMAC_SHA2_checksum(krb5_context context, struct _krb5_key_data *key, const void *data, size_t len, unsigned usage, Checksum *result) { krb5_error_code ret; const EVP_MD *md; unsigned char hmac[EVP_MAX_MD_SIZE]; unsigned int hmaclen = sizeof(hmac); ret = _krb5_aes_sha2_md_for_enctype(context, key->key->keytype, &md); if (ret) return ret; HMAC(md, key->key->keyvalue.data, key->key->keyvalue.length, data, len, hmac, &hmaclen); heim_assert(result->checksum.length <= hmaclen, "SHA2 internal error"); memcpy(result->checksum.data, hmac, result->checksum.length); return 0; }
static krb5_error_code xcc_create(krb5_context context, krb5_xcc *x, CFUUIDRef uuid) { const void *keys[] = { (void *)kHEIMObjectType, (void *)kHEIMAttrType, (void *)kHEIMAttrUUID }; const void *values[] = { (void *)kHEIMObjectKerberos, (void *)kHEIMTypeKerberos, (void *)uuid }; CFDictionaryRef attrs; krb5_error_code ret; CFErrorRef error = NULL; CFIndex num_keys = sizeof(keys)/sizeof(keys[0]); if (uuid == NULL) num_keys -= 1; attrs = CFDictionaryCreate(NULL, keys, values, num_keys, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); heim_assert(attrs != NULL, "Failed to create dictionary"); /* * Contract with HeimCredCreate is creates a uuid's when they are * not set on the attributes passed in. */ x->cred = HeimCredCreate(attrs, &error); CFRelease(attrs); if (x->cred) { heim_assert(x->uuid == NULL, "credential should not already have a UUID"); x->uuid = HeimCredGetUUID(x->cred); heim_assert(x->uuid != NULL, "no uuid for credential?"); CFRetain(x->uuid); ret = 0; genName(x); } else { ret = _krb5_set_cf_error_message(context, ENOMEM, error, N_("no reply from GSSCred", "")); } CFRELEASE_NULL(error); return ret; }
static void * _heim_create_cf_instance(CFTypeID typeID, CFIndex size, char *category) { heim_assert(size >= sizeof(CFRuntimeBase), "cf runtime size too small"); CFTypeRef type = _CFRuntimeCreateInstance(NULL, typeID, size - sizeof(struct heim_base), (unsigned char *)category); if (type) memset(((uint8_t *)type) + sizeof(struct heim_base), 0, size - sizeof(struct heim_base)); return (void *)type; }
static void eval_repeat(heim_dict_t o) { heim_object_t or = heim_dict_get_value(o, HSTR("value")); heim_number_t n = heim_dict_get_value(o, HSTR("num")); int i, num; struct perf perf; perf_start(&perf); heim_assert(or != NULL, "value missing"); heim_assert(n != NULL, "num missing"); num = heim_number_get_int(n); heim_assert(num >= 0, "num >= 0"); for (i = 0; i < num; i++) eval_object(or); perf_stop(&perf); }
static heim_dict_t parse_dict(struct parse_ctx *ctx) { heim_dict_t dict; size_t count = 0; int ret; heim_assert(*ctx->p == '{', "string doesn't start with {"); dict = heim_dict_create(11); if (dict == NULL) { ctx->error = heim_error_create_enomem(); return NULL; } ctx->p += 1; /* safe because parse_pair() calls white_spaces() first */ while ((ret = parse_pair(dict, ctx)) > 0) count++; if (ret < 0) { heim_release(dict); return NULL; } if (count == 1 && !(ctx->flags & HEIM_JSON_F_NO_DATA_DICT)) { heim_object_t v = heim_dict_copy_value(dict, heim_tid_data_uuid_key); /* * Binary data encoded as a dict with a single magic key with * base64-encoded value? Decode as heim_data_t. */ if (v != NULL && heim_get_tid(v) == HEIM_TID_STRING) { void *buf; size_t len; buf = malloc(strlen(heim_string_get_utf8(v))); if (buf == NULL) { heim_release(dict); heim_release(v); ctx->error = heim_error_create_enomem(); return NULL; } len = base64_decode(heim_string_get_utf8(v), buf); heim_release(v); if (len == -1) { free(buf); return dict; /* assume aliasing accident */ } heim_release(dict); return (heim_dict_t)heim_data_ref_create(buf, len, free); } } return dict; }
/** * Open a transaction on the given db. * * @param db Open DB handle * @param error Output error object * * @return 0 on success, system error otherwise * * @addtogroup heimbase */ int heim_db_begin(heim_db_t db, int read_only, heim_error_t *error) { int ret; if (heim_get_tid(db) != HEIM_TID_DB) return EINVAL; if (db->in_transaction && (read_only || !db->ro_tx || (!read_only && !db->ro_tx))) heim_abort("DB already in transaction"); if (db->plug->setf == NULL || db->plug->delf == NULL) return EINVAL; if (db->plug->beginf) { ret = db->plug->beginf(db->db_data, read_only, error); } else if (!db->in_transaction) { /* Try to emulate transactions */ if (db->plug->lockf == NULL) return EINVAL; /* can't lock? -> no transactions */ /* Assume unlock provides sync/durability */ ret = db->plug->lockf(db->db_data, read_only, error); if (ret) return ret; ret = db_replay_log(db, error); if (ret) { ret = db->plug->unlockf(db->db_data, error); return ret; } db->set_keys = heim_dict_create(11); if (db->set_keys == NULL) return ENOMEM; db->del_keys = heim_dict_create(11); if (db->del_keys == NULL) { heim_release(db->set_keys); db->set_keys = NULL; return ENOMEM; } } else { heim_assert(read_only == 0, "Internal error"); ret = db->plug->lockf(db->db_data, 0, error); if (ret) return ret; } db->in_transaction = 1; db->ro_tx = !!read_only; return 0; }
static krb5_error_code KRB5_CALLCONV xcc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { krb5_xcc *x = XCACHE(id); krb5_error_code ret; if (x->primary_principal) krb5_free_principal(context, x->primary_principal); ret = krb5_copy_principal(context, primary_principal, &x->primary_principal); if (ret) return ret; CFRELEASE_NULL(x->clientName); x->clientName = CFStringCreateFromPrincipal(context, primary_principal); if (x->clientName == NULL) return krb5_enomem(context); if (x->cred == NULL) { ret = xcc_create(context, x, x->uuid); if (ret) return ret; } else { const void *remove_keys[] = { kHEIMAttrType, kHEIMAttrParentCredential }; const void *remove_values[] = { (void *)kHEIMTypeKerberos, x->uuid, }; CFDictionaryRef query; query = CFDictionaryCreate(NULL, remove_keys, remove_values, sizeof(remove_keys) / sizeof(remove_keys[0]), NULL, NULL); heim_assert(query != NULL, "Failed to create dictionary"); HeimCredDeleteQuery(query, NULL); CFRelease(query); } if (!HeimCredSetAttribute(x->cred, kHEIMAttrClientName, x->clientName, NULL)) {\ ret = EINVAL; krb5_set_error_message(context, ret, "failed to store credential to %s", x->cache_name); } return ret; }
int _heim_scram_unparse(heim_scram_pairs *d, heim_scram_data *out) { size_t i, len; unsigned char *p; heim_assert(d->len != 0, "no key pairs"); len = d->len * 3 - 1; /* t=, */ if (d->flags & (SCRAM_BINDINGS_YES|SCRAM_BINDINGS_NO)) len += 2; for (i = 0; i < d->len; i++) len += d->val[i].data.length; scram_data_alloc(out, len); p = out->data; if (d->flags & SCRAM_BINDINGS_YES) { memcpy(p, "y,", 2); p += 2; } else if (d->flags & SCRAM_BINDINGS_NO) { memcpy(p, "n,", 2); p += 2; } for (i = 0; i < d->len; i++) { *p++ = d->val[i].type; *p++ = '='; memcpy(p, d->val[i].data.data, d->val[i].data.length); p += d->val[i].data.length; if (i + 1 < d->len) *p++ = ','; } heim_assert((p - (unsigned char *)out->data) == out->length, "generated packet wrong length"); return 0; }
static krb5_error_code tkt_store(krb5_context context, krb5_tkt_creds_context ctx, krb5_data *in, krb5_data *out, krb5_realm *realm, unsigned int *flags) { krb5_boolean bret; _krb5_debugx(context, 10, "tkt_step_store: %s", ctx->server_name); ctx->error = 0; ctx->state = NULL; if (ctx->options & KRB5_GC_NO_STORE) return 0; if (ctx->tickets) { store_tgts(context, ctx->ccache, ctx->tickets); free(ctx->tickets); ctx->tickets = NULL; } heim_assert(ctx->cred != NULL, "store but no credential"); krb5_cc_store_cred(context, ctx->ccache, ctx->cred); /* * Store an referrals entry since the server changed from that * expected and if we want to find it again next time, it * better have the right name. * * We only need to compare any realm since the referrals * matching code will do the same for us. */ bret = krb5_principal_compare_any_realm(context, ctx->cred->server, ctx->in_cred->server); if (!bret) { krb5_creds ref = *ctx->cred; krb5_principal_data refp = *ctx->in_cred->server; refp.realm = ""; ref.server = &refp; krb5_cc_store_cred(context, ctx->ccache, &ref); } return 0; }
static void db_dealloc(void *arg) { heim_db_t db = arg; heim_assert(!db->in_transaction, "rollback or commit heim_db_t before releasing it"); if (db->db_data) (void) db->plug->closef(db->db_data, NULL); heim_release(db->to_release); heim_release(db->dbtype); heim_release(db->dbname); heim_release(db->options); heim_release(db->set_keys); heim_release(db->del_keys); heim_release(db->error); }
static heim_string_t parse_string(struct parse_ctx *ctx) { const uint8_t *start; int quote = 0; heim_assert(*ctx->p == '"', "string doesnt' start with \""); start = ++ctx->p; while (ctx->p < ctx->pend) { if (*ctx->p == '\n') { ctx->lineno++; } else if (*ctx->p == '\\') { if (ctx->p + 1 == ctx->pend) goto out; ctx->p += 1; quote = 1; } else if (*ctx->p == '"') { heim_object_t o; if (quote) { char *p0, *p; p = p0 = malloc(ctx->p - start); if (p == NULL) goto out; while (start < ctx->p) { if (*start == '\\') { start++; /* XXX validate qouted char */ } *p++ = *start++; } o = heim_string_create_with_bytes(p0, p - p0); free(p0); } else { o = heim_string_create_with_bytes(start, ctx->p - start); } ctx->p += 1; return o; } ctx->p += 1; } out: ctx->error = heim_error_create(EINVAL, "ran out of string"); return NULL; }
static heim_array_t parse_array(struct parse_ctx *ctx) { heim_array_t array = heim_array_create(); int ret; heim_assert(*ctx->p == '[', "array doesn't start with ["); ctx->p += 1; while ((ret = parse_item(array, ctx)) > 0) ; if (ret < 0) { heim_release(array); return NULL; } return array; }
static heim_dict_t parse_dict(struct parse_ctx *ctx) { heim_dict_t dict = heim_dict_create(11); int ret; heim_assert(*ctx->p == '{', "string doesn't start with {"); ctx->p += 1; while ((ret = parse_pair(dict, ctx)) > 0) ; if (ret < 0) { heim_release(dict); return NULL; } return dict; }
static krb5_error_code DB_unlock(krb5_context context, HDB *db) { DB *d = (DB*)db->hdb_db; int fd; if (db->lock_count > 1) { db->lock_count--; return 0; } heim_assert(db->lock_count == 1, "HDB lock/unlock sequence does not match"); db->lock_count--; if ((*d->fd)(d, &fd)) return HDB_ERR_CANT_LOCK_DB; return hdb_unlock(fd); }
void heim_ipc_semaphore_release(heim_isemaphore s) { #ifdef HAVE_GCD dispatch_release((dispatch_semaphore_t)s); #elif !defined(ENABLE_PTHREAD_SUPPORT) heim_assert(0, "no semaphore support w/o pthreads"); #else HEIMDAL_MUTEX_lock(&s->mutex); if (s->counter != 0) abort(); HEIMDAL_MUTEX_unlock(&s->mutex); HEIMDAL_MUTEX_destroy(&s->mutex); pthread_cond_destroy(&s->cond); free(s); #endif }
static int json_db_unlock(void *db, heim_error_t *error) { json_db_t jsondb = db; int ret = 0; heim_assert(jsondb->locked, "DB not locked when unlock attempted"); if (jsondb->fd > -1) ret = close(jsondb->fd); jsondb->fd = -1; jsondb->read_only = 0; jsondb->locked = 0; if (jsondb->locked_needs_unlink) unlink(heim_string_get_utf8(jsondb->bkpname)); jsondb->locked_needs_unlink = 0; return ret; }
static void retry_timer(void) { dispatch_time_t t; heim_assert(g_dnsRef == NULL, "called create when a connection already existed"); if (g_restart_timer) return; g_restart_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, g_queue); t = dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC); dispatch_source_set_timer(g_restart_timer, t, 0, NSEC_PER_SEC); dispatch_source_set_event_handler(g_restart_timer, ^{ create_dns_sd(); dispatch_release(g_restart_timer); g_restart_timer = NULL; });