static krb5_error_code kcm_op_get_ntlm_user_list(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { struct kcm_ntlm_cred *c; krb5_error_code ret; for (c = ntlm_head; c != NULL; c = c->next) { if (!kcm_is_same_session(client, c->uid, c->session)) continue; ret = krb5_store_uint32(response, 1); if (ret) return ret; ret = krb5_store_stringz(response, c->user); if (ret) return ret; ret = krb5_store_stringz(response, c->domain); if (ret) return ret; } return krb5_store_uint32(response, 0); }
static krb5_error_code kcm_op_get_default_cache(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { struct kcm_default_cache *c; krb5_error_code ret; const char *name = NULL; char *n = NULL; KCM_LOG_REQUEST(context, client, opcode); for (c = default_caches; c != NULL; c = c->next) { if (kcm_is_same_session(client, c->uid, c->session)) { name = c->name; break; } } if (name == NULL) name = n = kcm_ccache_first_name(client); if (name == NULL) { asprintf(&n, "%d", (int)client->uid); name = n; } if (name == NULL) return ENOMEM; ret = krb5_store_stringz(response, name); if (n) free(n); return ret; }
static struct kcm_ntlm_cred * find_ntlm_cred(const char *user, const char *domain, kcm_client *client) { struct kcm_ntlm_cred *c; for (c = ntlm_head; c != NULL; c = c->next) if ((user[0] == '\0' || strcmp(user, c->user) == 0) && (domain == NULL || strcmp(domain, c->domain) == 0) && kcm_is_same_session(client, c->uid, c->session)) return c; return NULL; }
static void kcm_drop_default_cache(krb5_context context, kcm_client *client, char *name) { struct kcm_default_cache **c; for (c = &default_caches; *c != NULL; c = &(*c)->next) { if (!kcm_is_same_session(client, (*c)->uid, (*c)->session)) continue; if (strcmp((*c)->name, name) == 0) { struct kcm_default_cache *h = *c; *c = (*c)->next; free(h->name); free(h); break; } } }
char * kcm_ccache_first_name(kcm_client *client) { kcm_ccache p; char *name = NULL; HEIMDAL_MUTEX_lock(&ccache_mutex); for (p = ccache_head; p != NULL; p = p->next) { if (kcm_is_same_session(client, p->uid, p->session)) break; } if (p) name = strdup(p->name); HEIMDAL_MUTEX_unlock(&ccache_mutex); return name; }
static krb5_error_code kcm_op_set_default_cache(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { struct kcm_default_cache *c; krb5_error_code ret; char *name; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); for (c = default_caches; c != NULL; c = c->next) { if (kcm_is_same_session(client, c->uid, c->session)) break; } if (c == NULL) { c = malloc(sizeof(*c)); if (c == NULL) return ENOMEM; c->session = client->session; c->uid = client->uid; c->name = strdup(name); c->next = default_caches; default_caches = c; } else { free(c->name); c->name = strdup(name); } return 0; }
static krb5_error_code kcm_op_del_ntlm_cred(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { struct kcm_ntlm_cred **cp, *c; char *user = NULL, *domain = NULL; krb5_error_code ret; ret = krb5_ret_stringz(request, &user); if (ret) goto error; ret = krb5_ret_stringz(request, &domain); if (ret) goto error; for (cp = &ntlm_head; *cp != NULL; cp = &(*cp)->next) { if (strcmp(user, (*cp)->user) == 0 && strcmp(domain, (*cp)->domain) == 0 && kcm_is_same_session(client, (*cp)->uid, (*cp)->session)) { c = *cp; *cp = c->next; free_cred(c); break; } } error: free(user); free(domain); return ret; }
krb5_error_code kcm_access(krb5_context context, kcm_client *client, kcm_operation opcode, kcm_ccache ccache) { int read_p = 0; int write_p = 0; uint16_t mask; krb5_error_code ret; KCM_ASSERT_VALID(ccache); switch (opcode) { case KCM_OP_INITIALIZE: case KCM_OP_DESTROY: case KCM_OP_STORE: case KCM_OP_REMOVE_CRED: case KCM_OP_SET_FLAGS: case KCM_OP_CHOWN: case KCM_OP_CHMOD: case KCM_OP_GET_INITIAL_TICKET: case KCM_OP_GET_TICKET: case KCM_OP_MOVE_CACHE: case KCM_OP_SET_DEFAULT_CACHE: case KCM_OP_SET_KDC_OFFSET: write_p = 1; read_p = 0; break; case KCM_OP_NOOP: case KCM_OP_GET_NAME: case KCM_OP_RESOLVE: case KCM_OP_GEN_NEW: case KCM_OP_RETRIEVE: case KCM_OP_GET_PRINCIPAL: case KCM_OP_GET_CRED_UUID_LIST: case KCM_OP_GET_CRED_BY_UUID: case KCM_OP_GET_CACHE_UUID_LIST: case KCM_OP_GET_CACHE_BY_UUID: case KCM_OP_GET_DEFAULT_CACHE: case KCM_OP_GET_KDC_OFFSET: write_p = 0; read_p = 1; break; default: ret = KRB5_FCC_PERM; goto out; } if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) { /* System caches cannot be reinitialized or destroyed by users */ if (opcode == KCM_OP_INITIALIZE || opcode == KCM_OP_DESTROY || opcode == KCM_OP_REMOVE_CRED || opcode == KCM_OP_MOVE_CACHE) { ret = KRB5_FCC_PERM; goto out; } /* Let root always read system caches */ if (CLIENT_IS_ROOT(client)) { ret = 0; goto out; } } /* start out with "other" mask */ mask = S_IROTH|S_IWOTH; /* root can do anything */ if (CLIENT_IS_ROOT(client)) { if (read_p) mask |= S_IRUSR|S_IRGRP|S_IROTH; if (write_p) mask |= S_IWUSR|S_IWGRP|S_IWOTH; } /* same session same as owner */ if (kcm_is_same_session(client, ccache->uid, ccache->session)) { if (read_p) mask |= S_IROTH; if (write_p) mask |= S_IWOTH; } /* owner */ if (client->uid == ccache->uid) { if (read_p) mask |= S_IRUSR; if (write_p) mask |= S_IWUSR; } /* group */ if (client->gid == ccache->gid) { if (read_p) mask |= S_IRGRP; if (write_p) mask |= S_IWGRP; } ret = (ccache->mode & mask) ? 0 : KRB5_FCC_PERM; out: if (ret) { kcm_log(2, "Process %d is not permitted to call %s on cache %s", client->pid, kcm_op2string(opcode), ccache->name); } return ret; }