/* * Copyright (c) 2005, PADL Software Pty Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of PADL Software nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #ifndef __KCM_LOCL_H__ #define __KCM_LOCL_H__ #include "headers.h" #include #define KCM_LOG_REQUEST(_context, _client, _opcode) do { \ kcm_log(1, "%s request by process %d/uid %d", \ kcm_op2string(_opcode), (_client)->pid, (_client)->uid); \ } while (0) #define KCM_LOG_REQUEST_NAME(_context, _client, _opcode, _name) do { \ kcm_log(1, "%s request for cache %s by process %d/uid %d", \ kcm_op2string(_opcode), (_name), (_client)->pid, (_client)->uid); \ } while (0) /* Cache management */ #define KCM_FLAGS_VALID 0x0001 #define KCM_FLAGS_USE_KEYTAB 0x0002 #define KCM_FLAGS_RENEWABLE 0x0004 #define KCM_FLAGS_OWNER_IS_SYSTEM 0x0008 #define KCM_FLAGS_USE_CACHED_KEY 0x0010 #define KCM_MASK_KEY_PRESENT ( KCM_FLAGS_USE_KEYTAB | \ KCM_FLAGS_USE_CACHED_KEY ) struct kcm_ccache_data; struct kcm_creds; typedef struct kcm_cursor { pid_t pid; u_int32_t key; struct kcm_creds *credp; /* pointer to next credential */ struct kcm_cursor *next; } kcm_cursor; typedef struct kcm_ccache_data { char *name; unsigned refcnt; u_int16_t flags; u_int16_t mode; uid_t uid; gid_t gid; krb5_principal client; /* primary client principal */ krb5_principal server; /* primary server principal (TGS if NULL) */ struct kcm_creds { krb5_creds cred; /* XXX would be useful for have ACLs on creds */ struct kcm_creds *next; } *creds; u_int32_t n_cursor; kcm_cursor *cursors; krb5_deltat tkt_life; krb5_deltat renew_life; union { krb5_keytab keytab; krb5_keyblock keyblock; } key; HEIMDAL_MUTEX mutex; struct kcm_ccache_data *next; } kcm_ccache_data; #define KCM_ASSERT_VALID(_ccache) do { \ if (((_ccache)->flags & KCM_FLAGS_VALID) == 0) \ krb5_abortx(context, "kcm_free_ccache_data: ccache invalid"); \ else if ((_ccache)->refcnt == 0) \ krb5_abortx(context, "kcm_free_ccache_data: ccache refcnt == 0"); \ } while (0) typedef kcm_ccache_data *kcm_ccache; char *kcm_ccache_nextid(pid_t pid, uid_t uid, gid_t gid); /* foo_internal routines assume caller has acquired lock */ /* locking is there in case we eventually multithread */ krb5_error_code kcm_debug_ccache(krb5_context context); krb5_error_code kcm_zero_ccache_data(krb5_context context, kcm_ccache cache); krb5_error_code kcm_zero_ccache_data_internal(krb5_context context, kcm_ccache_data *cache); krb5_error_code kcm_retain_ccache(krb5_context context, kcm_ccache ccache); krb5_error_code kcm_release_ccache(krb5_context context, kcm_ccache *ccache); krb5_error_code kcm_ccache_new(krb5_context context, const char *name, kcm_ccache *ccache); krb5_error_code kcm_ccache_destroy_if_empty(krb5_context context, kcm_ccache ccache); krb5_error_code kcm_ccache_acquire(krb5_context context, kcm_ccache ccache, krb5_creds **credp); krb5_error_code kcm_ccache_refresh(krb5_context context, kcm_ccache ccache, krb5_creds **credp); krb5_error_code kcm_ccache_gen_new(krb5_context context, pid_t pid, uid_t uid, gid_t gid, kcm_ccache *ccache); krb5_error_code kcm_ccache_resolve(krb5_context context, const char *name, kcm_ccache *ccache); krb5_error_code kcm_ccache_destroy(krb5_context context, const char *name); krb5_error_code kcm_ccache_store_cred_internal(krb5_context context, kcm_ccache ccache, krb5_creds *creds, int copy, krb5_creds **out); krb5_error_code kcm_ccache_store_cred(krb5_context context, kcm_ccache ccache, krb5_creds *creds, int copy); krb5_error_code kcm_ccache_remove_cred_internal(krb5_context context, kcm_ccache ccache, krb5_flags whichfields, const krb5_creds *mcreds); krb5_error_code kcm_ccache_remove_cred(krb5_context context, kcm_ccache ccache, krb5_flags whichfields, const krb5_creds *mcreds); krb5_error_code kcm_ccache_retrieve_cred_internal(krb5_context context, kcm_ccache ccache, krb5_flags whichfields, const krb5_creds *mcreds, krb5_creds **creds); krb5_error_code kcm_ccache_retrieve_cred(krb5_context context, kcm_ccache ccache, krb5_flags whichfields, const krb5_creds *mcreds, krb5_creds **credp); krb5_error_code kcm_ccache_remove_creds_internal(krb5_context context, kcm_ccache ccache); krb5_error_code kcm_ccache_remove_creds(krb5_context context, kcm_ccache ccache); /* Credentials enumeration */ krb5_error_code kcm_cursor_new(krb5_context context, pid_t pid, kcm_ccache ccache, u_int32_t *cursor); krb5_error_code kcm_cursor_find(krb5_context context, pid_t pid, kcm_ccache ccache, u_int32_t key, kcm_cursor **cursor); krb5_error_code kcm_cursor_delete(krb5_context context, pid_t pid, kcm_ccache ccache, u_int32_t key); /* Event management */ typedef struct kcm_event { int valid; time_t fire_time; unsigned fire_count; time_t expire_time; time_t backoff_time; enum { KCM_EVENT_NONE = 0, KCM_EVENT_ACQUIRE_CREDS, KCM_EVENT_RENEW_CREDS, KCM_EVENT_DESTROY_CREDS, KCM_EVENT_DESTROY_EMPTY_CACHE } action; kcm_ccache ccache; struct kcm_event *next; } kcm_event; /* wakeup interval for event queue */ #define KCM_EVENT_QUEUE_INTERVAL 60 #define KCM_EVENT_DEFAULT_BACKOFF_TIME 5 #define KCM_EVENT_MAX_BACKOFF_TIME (12 * 60 * 60) krb5_error_code kcm_ccache_enqueue_default(krb5_context context, kcm_ccache ccache, krb5_creds *newcred); krb5_error_code kcm_enqueue_event(krb5_context context, kcm_event *event); /* don't grab lock */ krb5_error_code kcm_enqueue_event_internal(krb5_context context, kcm_event *event); /* fire time is relative to now */ krb5_error_code kcm_enqueue_event_relative(krb5_context context, kcm_event *event); krb5_error_code kcm_remove_event(krb5_context context, kcm_event *event); krb5_error_code kcm_cleanup_events(krb5_context context, kcm_ccache ccache); krb5_error_code kcm_run_events(krb5_context context, time_t now); krb5_error_code kcm_debug_events(krb5_context context); /* Operation dispatch */ /* Request format is LENGTH | MAJOR | MINOR | OPERATION | request */ /* Response format is LENGTH | STATUS | response */ typedef struct kcm_client { pid_t pid; uid_t uid; gid_t gid; } kcm_client; /* Access-checked cache management */ krb5_error_code kcm_ccache_resolve_client(krb5_context context, kcm_client *client, kcm_operation opcode, const char *name, kcm_ccache *ccache); krb5_error_code kcm_ccache_destroy_client(krb5_context context, kcm_client *client, const char *name); krb5_error_code kcm_ccache_new_client(krb5_context context, kcm_client *client, const char *name, kcm_ccache *ccache); const char *kcm_op2string(kcm_operation operation); /* Dispatch table */ /* passed in OPERATION | ... ; returns STATUS | ... */ typedef krb5_error_code (*kcm_method)(krb5_context, kcm_client *, kcm_operation, krb5_storage *, krb5_storage *); krb5_error_code kcm_dispatch(krb5_context context, kcm_client *sd, krb5_data *request, krb5_data *response); /* Access checking */ krb5_error_code kcm_access(krb5_context context, kcm_client *client, kcm_operation opcode, kcm_ccache ccache); krb5_error_code kcm_chown(krb5_context context, kcm_client *client, kcm_ccache ccache, uid_t uid, gid_t gid); krb5_error_code kcm_chmod(krb5_context context, kcm_client *client, kcm_ccache ccache, u_int16_t mode); krb5_error_code kcm_internal_ccache(krb5_context context, kcm_ccache c, krb5_ccache id); void kcm_openlog(void); void kcm_log(int level, const char *fmt, ...); char *kcm_log_msg(int level, const char *fmt, ...); char *kcm_log_msg_va(int level, const char *fmt, va_list ap); #define DEFAULT_LOG_DEST "0/FILE:" LOCALSTATEDIR "/log/kcmd.log" #define _PATH_KCM_CONF SYSCONFDIR "/kcm.conf" void kcm_configure(int argc, char **argv); void kcm_loop(void); extern krb5_context kcm_context; extern char *socket_path; extern size_t max_request; extern sig_atomic_t exit_flag; extern int name_constraints; #if 0 extern const krb5_cc_ops krb5_kcmss_ops; #endif #endif /* __KCM_LOCL_H__ */