From 3d6591dd63c23bcc0ae68e94a960c85fd53daad0 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 5 Jun 2006 04:30:35 +0000 Subject: more updates git-svn-id: svn://anonsvn.mit.edu/krb5/branches/ccapi@18082 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/ccapi/NTMakefile | 25 ++ src/lib/ccapi/client/NTMakefile | 13 +- src/lib/ccapi/client/cacheapi.def | 29 -- src/lib/ccapi/client/dllmain.c | 15 - src/lib/ccapi/common/NTMakefile | 2 +- src/lib/ccapi/doc/implementation-notes.txt | 156 +++++++ src/lib/ccapi/include/CredentialsCache.h | 4 + src/lib/ccapi/include/CredentialsCache2.h | 22 +- src/lib/ccapi/include/datastore.h | 189 +++++++++ src/lib/ccapi/include/rpc_auth.h | 71 ++++ src/lib/ccapi/server/NTMakefile | 21 +- src/lib/ccapi/server/datastore.h | 189 --------- src/lib/ccapi/server/rpc_auth.h | 71 ---- src/lib/ccapi/unit-test/NTMakefile | 56 ++- src/lib/ccapi/unit-test/t_ccache.c | 24 +- src/lib/ccapi/unit-test/t_context.c | 34 +- src/lib/ccapi/unit-test/t_server.c | 4 +- src/lib/ccapi/windows/NTMakefile | 35 ++ src/lib/ccapi/windows/cacheapi.def | 29 ++ src/lib/ccapi/windows/client.c | 120 ++++++ src/lib/ccapi/windows/dllmain.c | 15 + src/lib/ccapi/windows/ntccrpc.acf | 8 + src/lib/ccapi/windows/ntccrpc.idl | 31 ++ src/lib/ccapi/windows/server.c | 638 +++++++++++++++++++++++++++++ 24 files changed, 1422 insertions(+), 379 deletions(-) create mode 100644 src/lib/ccapi/NTMakefile delete mode 100644 src/lib/ccapi/client/cacheapi.def delete mode 100644 src/lib/ccapi/client/dllmain.c create mode 100644 src/lib/ccapi/doc/implementation-notes.txt create mode 100644 src/lib/ccapi/include/datastore.h create mode 100644 src/lib/ccapi/include/rpc_auth.h delete mode 100644 src/lib/ccapi/server/datastore.h delete mode 100644 src/lib/ccapi/server/rpc_auth.h create mode 100644 src/lib/ccapi/windows/NTMakefile create mode 100644 src/lib/ccapi/windows/cacheapi.def create mode 100644 src/lib/ccapi/windows/client.c create mode 100644 src/lib/ccapi/windows/dllmain.c create mode 100644 src/lib/ccapi/windows/ntccrpc.acf create mode 100644 src/lib/ccapi/windows/ntccrpc.idl create mode 100644 src/lib/ccapi/windows/server.c diff --git a/src/lib/ccapi/NTMakefile b/src/lib/ccapi/NTMakefile new file mode 100644 index 0000000..57c42e3 --- /dev/null +++ b/src/lib/ccapi/NTMakefile @@ -0,0 +1,25 @@ +CD = cd + +all: + $(CD) common + $(MAKE) -f NTMakefile all + $(CD) ../client + $(MAKE) -f NTMakefile all + $(CD) ../server + $(MAKE) -f NTMakefile all + $(CD) ../windows + $(MAKE) -f NTMakefile all + $(CD) .. + +clean: + $(CD) common + $(MAKE) -f NTMakefile clean + $(CD) ../client + $(MAKE) -f NTMakefile clean + $(CD) ../server + $(MAKE) -f NTMakefile clean + $(CD) ../windows + $(MAKE) -f NTMakefile clean + $(CD) .. + + diff --git a/src/lib/ccapi/client/NTMakefile b/src/lib/ccapi/client/NTMakefile index f9d85b4..2ce87c3 100644 --- a/src/lib/ccapi/client/NTMakefile +++ b/src/lib/ccapi/client/NTMakefile @@ -1,6 +1,6 @@ !INCLUDE -CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsdll) +CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsmt) CC_CLIENT_OBJS = cacheapi.obj context.obj ccache.obj credentials.obj ccache_iterator.obj \ credentials_iterator.obj ccstring.obj ccapiv2.obj @@ -12,14 +12,7 @@ CC_COMMON_LIB = ..\common\cc_common.lib $(CC_CLIENT_LIB): $(CC_CLIENT_OBJS) $(implib) /NOLOGO /OUT:$@ $** -CCAPI_DLLFILE = krbcc32.dll - -WINLIBS = ws2_32.lib $(guilibsdll) msvcrt.lib - -$(CCAPI_DLLFILE): dllmain.obj $(CC_CLIENT_LIB) $(CC_COMMON_LIB) - $(link) /OUT:$@ $(ldebug) $(dlllflags) /NODEFAULTLIB:libcmt.lib -def:cacheapi.def $** $(WINLIBS) - -all: $(CCAPI_DLLFILE) +all: $(CC_CLIENT_LIB) clean: - del *.obj *.lib *.dll *.exp + del *.obj *.lib diff --git a/src/lib/ccapi/client/cacheapi.def b/src/lib/ccapi/client/cacheapi.def deleted file mode 100644 index c54cc11..0000000 --- a/src/lib/ccapi/client/cacheapi.def +++ /dev/null @@ -1,29 +0,0 @@ -EXPORTS - ; ccapi v3 only exports one function - cc_initialize @14 - - ; ccapi v2 compatibility functions - cc_close @2 - cc_create @3 - cc_destroy @4 - cc_free_NC_info @5 - cc_free_creds @6 - cc_free_name @7 - cc_free_principal @8 - cc_get_NC_info @9 - cc_get_change_time @10 - cc_get_cred_version @11 - cc_get_name @12 - cc_get_principal @13 - cc_lock_request @15 - cc_open @16 - cc_remove_cred @17 - cc_seq_fetch_NCs_begin @18 - cc_seq_fetch_NCs_end @19 - cc_seq_fetch_NCs_next @20 - cc_seq_fetch_creds_begin @21 - cc_seq_fetch_creds_end @22 - cc_seq_fetch_creds_next @23 - cc_set_principal @24 - cc_shutdown @25 - cc_store @26 diff --git a/src/lib/ccapi/client/dllmain.c b/src/lib/ccapi/client/dllmain.c deleted file mode 100644 index 6b4d6bf..0000000 --- a/src/lib/ccapi/client/dllmain.c +++ /dev/null @@ -1,15 +0,0 @@ -#include - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, - LPVOID lpvReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - default: - return TRUE; - } -} - diff --git a/src/lib/ccapi/common/NTMakefile b/src/lib/ccapi/common/NTMakefile index d0d92fc..a43985a 100644 --- a/src/lib/ccapi/common/NTMakefile +++ b/src/lib/ccapi/common/NTMakefile @@ -1,6 +1,6 @@ !INCLUDE -CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsdll) +CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsmt) CC_COMMON_OBJS = marshall.obj msg.obj generic_lists.obj diff --git a/src/lib/ccapi/doc/implementation-notes.txt b/src/lib/ccapi/doc/implementation-notes.txt new file mode 100644 index 0000000..e6150fb --- /dev/null +++ b/src/lib/ccapi/doc/implementation-notes.txt @@ -0,0 +1,156 @@ +The following are notes describing the requirements of the Platform +Specific code necessary for constructing a Portable CCAPI. + +Directory structure: + + lib/ccapi/client - platform independent client library + lib/ccapi/common - platform independent common library + lib/ccapi/include - platform independent header files + lib/ccapi/mac - macosx specific headers, libraries, executables + lib/ccapi/server - platform independent server library + lib/ccapi/windows - windows specific headers, libraries, executables + + +Platform Independent Design: + +The functionality of the Portable CCAPI is implemented in the platform +independent libraries. The common library encapsulates the functions +for managing generic lists, iterators, and messages as well as routines +formarshalling and unmarshalling. The client library provides the +client side routines for issuing requests to the ccapi server minus the +platform dependent glue required for shared library initialization, +cleanup, and interprocess communications. The server library provides +server side functionality for managing credential cache collections, +caches, credentials, iterators, and their handles minus the platform +dependent glue for process initialization, interprocess communication, +session security, and critical section enforcement. + + +Platform Dependent Design Requirements: + +The platform dependent code is responsible for producing a shared +client library: + + + the shared library is built from cc_client.lib and cc_common.lib plus + platform dependent glue + + - [windows] link cc_client.lib and cc_common.lib with platform + dependent routines and export list (.def) to produce + krbcc32.{lib,dll} + + + initialization and cleanup + + - [windows] provide DllMain entry point providing Process and Thread + attachment and detachment routines + + + implement cci_perform_rpc() function used by cc_client.lib + cc_int32 cci_perform_rpc(cc_msg_t *request, cc_msg_t **response) + + - cci_perform_rpc() takes an input request cc_msg_t object, flattens + it with cci_msg_flatten() and sends the contents of unsigned char + buffer request->flat of length request->flat_len to the server + utilizing a platform specific interprocess communication method. + + - upon IPC success, cci_perform_rpc() unflattens the response buffer + with cci_msg_unflatten() and returns the new cc_msg_t response + object to the caller. + + - cci_perform_rpc() is responsible for performing any necessary + session security management. For example, on Windows the Logon + Provider executes under the local machine's "SYSTEM" account within + session 0 and not under the account of the user that is logging in + nor within the session the user's desktop and applications will be + running within. It is the responsibility of cci_perform_rpc() and + the platform dependent IPC mechanism to communicate the user's + security identifiers to the server. + + For Windows, this means that the platform specific IPC messaging + allows a username and session identifier to be sent separate from + the username and session identifier that will be obtained via the + use of Local RPC. If the Local RPC authenticates the user as + "SYSTEM" and session 0, then the communicated values (if provided) + will be used instead. + + + implement client side of IPC routine. + + - [windows] the client side IPC routine is produced by compiling a + IDL file. The IDL defines an interface with a single function: + + __int32 ccapi_Message ( + [in] handle_t h, + [in, string] unsigned char * client_name, + [in] struct _LUID luid, + [in] __int32 in_len, + [in, string, size_is(in_len)] unsigned char * in_buf, + [in] __int32 out_size, + [out] __int32 * out_len, + [out, string, size_is(out_size)] unsigned char + out_buf[*]); + + The handle is a Local RPC specific handle used to identify the + request. The client_name and luid are the override values for the + username and session identifier for use during Windows login. The + rest of the parameters provide the input and output buffers as well + as allow communication of the actual length of the message data + that is required by cci_msg_unflatten(). + + + if the CCAPI server is per-session, the shared client library is + responsible for ensuring that an instance of the server is running in + the current session. If not, the library must initiate an instance + of the CCAPI server prior to performing any IPC requests. + +The platform dependent code is responsible for producing a server +executable: + + + The server executable is built from cc_server.lib and cc_common.lib + plus platform dependent glue. + + - [windows] The Windows CCAPI Server is being built using the + per-system model. The platform specific code is responsible for + providing NT Service Management routines for installation and + removal as well as the NT Service Entry Points used when the + process is started as an NT Service. + + link cc_server.lib and cc_common.lib with platform dependent + routines to produce krbcc32s.exe. + + + Based upon the platform requirements, the server may be constructed + to be per-session or per-system. The selected IPC mechanism must + enforce the appropriate scoping. + + + The platform dependent startup routines will perform platform + specific initialization including the IPC engine and call the + platform independent initialization routine ccs_serv_initialize() + + + The platform dependent shutdown routines will perform platform + specific cleanup including the IPC engine and call the platform + independent function ccs_serv_cleanup() prior to process termination. + + + For each inbound CCAPI request, the server will unmarshall the + request using cci_msg_unflatten() to produce a cc_msg_t object, + construct cc_auth_info_t and cc_session_info_t objects to represent + the platform dependent authentication and session data, call + ccs_serv_process_msg() to process the request, call cci_msg_flatten() + to marhall the response, transmit the response to the caller, and + then cleanup the request and response cc_msg_t objects with + cci_msg_destroy(). + + + The cc_auth_info_t and cc_session_info_t objects are structures + storing opaque binary (data, length) representations of the + authentication and session data. These are stored as part of ccache + collection and ccaches. ccs_serv_process_msg() will perform a binary + comparison of the stored data with the data provided in the current + request. If they do not match, the request will be denied. It is + necessary that the data generated data always be the same. If + username strings are not case-sensitive, they should be normalized + before being passed to ccs_serv_process_msg(). + + + The current cc_server.lib routines assume that one request at a time + is being processed. If the IPC engine allows for more than one + request to be simultaneously received in separate threads, then the + call to ccs_serv_process_msg() must be wrapped by a critical section. + Future enhancements to cc_server.lib will allow for per-object + mutexes. When available the platform specific glue must provide + functions to create, obtain, release, and destroy mutex objects. + + diff --git a/src/lib/ccapi/include/CredentialsCache.h b/src/lib/ccapi/include/CredentialsCache.h index 7143da4..12748bb 100644 --- a/src/lib/ccapi/include/CredentialsCache.h +++ b/src/lib/ccapi/include/CredentialsCache.h @@ -69,6 +69,10 @@ #include #endif +#if defined(_WIN32) +#include +#endif + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/src/lib/ccapi/include/CredentialsCache2.h b/src/lib/ccapi/include/CredentialsCache2.h index 214d93a..706c869 100644 --- a/src/lib/ccapi/include/CredentialsCache2.h +++ b/src/lib/ccapi/include/CredentialsCache2.h @@ -87,10 +87,10 @@ typedef struct cc_credentials_v5_compat { char* client; char* server; cc_data_compat keyblock; - cc_time_t authtime; - cc_time_t starttime; - cc_time_t endtime; - cc_time_t renew_till; + cc_time authtime; + cc_time starttime; + cc_time endtime; + cc_time renew_till; cc_uint32 is_skey; cc_uint32 ticket_flags; cc_data_compat** addresses; @@ -185,6 +185,13 @@ enum { CC_CRED_MAX }; +enum { + CC_LOCK_UNLOCK = 1, + CC_LOCK_READER = 2, + CC_LOCK_WRITER = 3, + CC_LOCK_NOBLOCK = 16 +}; + CCACHE_API cc_int32 cc_shutdown ( apiCB** ioContext); @@ -194,7 +201,7 @@ CCACHE_API cc_int32 cc_get_NC_info ( CCACHE_API cc_int32 cc_get_change_time ( apiCB* inContext, - cc_time_t* outTime); + cc_time* outTime); CCACHE_API cc_int32 cc_open ( apiCB* inContext, @@ -293,6 +300,11 @@ CCACHE_API cc_int32 cc_free_NC_info ( apiCB* inContext, infoNC*** ioInfo); +CCACHE_API cc_int32 cc_lock_request( + apiCB* inContext, + const ccache_p* inCCache, + const cc_int32 lock_type); + #if TARGET_OS_MAC #if defined(__MWERKS__) #pragma enumsalwaysint reset diff --git a/src/lib/ccapi/include/datastore.h b/src/lib/ccapi/include/datastore.h new file mode 100644 index 0000000..4f119f9 --- /dev/null +++ b/src/lib/ccapi/include/datastore.h @@ -0,0 +1,189 @@ +/* $Copyright: + * + * Copyright 2004-2006 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require a + * specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute + * this software and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of M.I.T. not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Furthermore if you + * modify this software you must label your software as modified software + * and not distribute it in such a fashion that it might be confused with + * the original MIT software. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, FundsXpress, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without prior + * written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the MIT + * trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * $ + */ +/* + * Prototypes and data structures for datastore. + * + */ + + +#ifndef __CCDATASTOREH__ +#define __CCDATASTOREH__ + +#include "CredentialsCache.h" +#include "rpc_auth.h" +#include "generic_lists.h" + +enum cc_list_type { + generic = 0, + context, + cache, + credentials +}; + +struct cc_context_iterate_t { + cc_context_list_node_t* next; +}; +typedef struct cc_context_iterate_t cc_context_iterate_t; + +struct cc_ccache_iterate_t { + cc_ccache_list_node_t* next; +}; +typedef struct cc_ccache_iterate_t cc_ccache_iterate_t; + +struct cc_credentials_iterate_t { + cc_credentials_list_node_t* next; +}; +typedef struct cc_credentials_iterate_t cc_credentials_iterate_t; + +struct cc_lock { + cc_uint32 read_locks; /* count of read locks (>= 0) */ + cc_uint32 write_locks; /* count of write locks (0 or 1) */ + void * platform_data; /* platform specific implementation data */ +}; +typedef struct cc_lock cc_lock_t; + + +struct cc_server_context_t { + cc_ccache_list_head_t* ccaches; /*our ccaches*/ + cc_generic_list_head_t* active_iterators; /*active ccache iterators*/ + cc_int32 api_version; /*Version our client passed in on init (ccapi_version_X) */ + cc_auth_info_t* auth_info; /*auth info passed in from RPC*/ + cc_session_info_t* session_info; /*session info passed in from RPC*/ + cc_time64 changed; /*date of last change to this context*/ + cc_int32 error; /*last error code*/ + cc_lock_t locks; /*are we locked?*/ +}; +typedef struct cc_server_context_t cc_server_context_t; + +struct cc_server_ccache_t { + char* name; /*name of this ccache*/ + char* principal_v4; /*v4 principal associated with this cache*/ + char* principal_v5; /*v5 principal associated with this cache*/ + cc_uint32 versions; /*versions of creds supported (from cc_credentials enum in CredentialsCache.h)*/ + cc_time64 changed; /*date of last change to ccache*/ + cc_int32 kdc_set; /*is the KDC time offset initialized?*/ + cc_time64 kdc_offset; /*offset of our clock relative kdc*/ + cc_time64 last_default; /*the last date when we were default*/ + cc_int32 is_default; /*is this the default cred on this ccache?*/ + cc_generic_list_head_t* active_iterators; /*iterators which clients have opened on this cache*/ + cc_credentials_list_head_t* creds; /*list of creds stored in this ccache*/ + cc_server_context_t* mycontext; /*context to which I belong*/ + cc_lock_t locks; /*are we locked?*/ +}; +typedef struct cc_server_ccache_t cc_server_ccache_t; + +struct cc_server_credentials_t { + cc_int32 is_default; /*Are we the default cred? (first in list)*/ + cc_credentials_union creds; +}; +typedef struct cc_server_credentials_t cc_server_credentials_t; + + +/*Note: cci means Credential Cache Internal, to differentiate from exported API macros*/ + +cc_int32 ccs_context_iterate_has_next(struct cc_context_iterate_t *iterate); +cc_int32 ccs_context_iterate_next(struct cc_context_iterate_t *iterate, cc_context_list_node_t**); + +cc_int32 ccs_ccache_iterate_has_next(struct cc_ccache_iterate_t *iterate); +cc_int32 ccs_ccache_iterate_next(struct cc_ccache_iterate_t *iterate, cc_ccache_list_node_t**); + +cc_int32 ccs_credentials_iterate_has_next(cc_credentials_iterate_t *iterate); +cc_int32 ccs_credentials_iterate_next(cc_credentials_iterate_t *iterate, cc_credentials_list_node_t **); + +cc_int32 ccs_context_list_new(cc_context_list_head_t**); +cc_int32 ccs_context_list_append(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**); +cc_int32 ccs_context_list_prepend(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**); +cc_int32 ccs_context_list_remove_element(cc_context_list_head_t* head, cc_context_list_node_t* rem); +cc_int32 ccs_context_list_iterator(cc_context_list_head_t *head, struct cc_context_iterate_t**); +cc_int32 ccs_context_free_iterator(struct cc_context_iterate_t *iterator); +cc_int32 ccs_context_list_destroy(cc_context_list_head_t* head) ; +cc_int32 ccs_context_list_copy(cc_context_list_head_t* head, cc_context_list_head_t**); + +cc_int32 ccs_ccache_list_new(cc_ccache_list_head_t**); +cc_int32 ccs_ccache_list_append(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**); +cc_int32 ccs_ccache_list_prepend(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**); +cc_int32 ccs_ccache_list_remove_element(cc_ccache_list_head_t* head, cc_ccache_list_node_t* rem); +cc_int32 ccs_ccache_list_iterator(cc_ccache_list_head_t *head, struct cc_ccache_iterate_t**); +cc_int32 ccs_ccache_free_iterator(struct cc_ccache_iterate_t *iterator); +cc_int32 ccs_ccache_list_destroy(cc_ccache_list_head_t* head) ; +cc_int32 ccs_ccache_list_copy(cc_ccache_list_head_t* head, cc_ccache_list_head_t**); + + +cc_int32 ccs_credentials_list_new(cc_credentials_list_head_t**); +cc_int32 ccs_credentials_list_append(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**); +cc_int32 ccs_credentials_list_prepend(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**); +cc_int32 ccs_credentials_list_remove_element(cc_credentials_list_head_t* head, cc_credentials_list_node_t* rem); +cc_int32 ccs_credentials_list_iterator(cc_credentials_list_head_t *head, cc_credentials_iterate_t**); +cc_int32 ccs_credentials_free_iterator(cc_credentials_iterate_t* iterator); +cc_int32 ccs_credentials_list_destroy(cc_credentials_list_head_t* head) ; +cc_int32 ccs_credentials_list_copy(cc_credentials_list_head_t* head, cc_credentials_list_head_t**) ; + + +cc_int32 ccs_context_new(int api_version, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_server_context_t** ) ; +cc_int32 ccs_context_get_default_ccache_name(cc_server_context_t* ctx, char **); +cc_int32 ccs_context_find_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t**); +cc_int32 ccs_context_open_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t** ); +cc_int32 ccs_context_create_ccache(cc_server_context_t* ctx, char *name, int creds_version, char *principal, cc_server_ccache_t**); +cc_int32 ccs_context_create_default_ccache(cc_server_context_t* ctx, int creds_version, char *principal, cc_server_ccache_t**); +cc_int32 ccs_context_ccache_iterator(cc_server_context_t* ctx, cc_ccache_iterate_t**); +cc_int32 ccs_context_compare(cc_server_context_t* a, cc_server_context_t* b); +cc_int32 ccs_context_destroy(cc_server_context_t* ctx); +cc_int32 ccs_context_rem_ccache(cc_server_context_t* ctx, cc_server_ccache_t* ccache); + +cc_int32 ccs_ccache_new(char *name, char *principal, int cred_vers, cc_server_ccache_t**); +cc_int32 ccs_ccache_check_version(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat); +cc_int32 ccs_ccache_check_principal(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat); +cc_int32 ccs_ccache_store_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials); +cc_int32 ccs_ccache_rem_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials); +cc_int32 ccs_ccache_move(cc_server_ccache_t *source, cc_server_ccache_t* destination); +cc_int32 ccs_ccache_get_kdc_time_offset(cc_server_ccache_t* ccache, cc_time64* offset); +cc_int32 ccs_ccache_set_kdc_time_offset(cc_server_ccache_t* ccache, cc_time64 offset); +cc_int32 ccs_ccache_clear_kdc_time_offset(cc_server_ccache_t* ccache); +cc_int32 ccs_ccache_new_iterator(cc_server_ccache_t* ccache, cc_credentials_iterate_t** iterator); +cc_int32 ccs_ccache_get_principal(cc_server_ccache_t* ccache, cc_int32 version, char ** principal); +cc_int32 ccs_ccache_set_principal(cc_server_ccache_t* ccache, cc_int32 version, char * principal); +cc_int32 ccs_ccache_free_principal(char * principal); +cc_int32 ccs_ccache_destroy(cc_server_ccache_t* ccache); +void ccs_ccache_changed(cc_server_ccache_t* ccache); +cc_int32 ccs_ccache_compare(cc_server_ccache_t* ccache1, cc_server_ccache_t* ccache2, cc_uint32 *result); +#endif /*__CCDATASTOREH__*/ diff --git a/src/lib/ccapi/include/rpc_auth.h b/src/lib/ccapi/include/rpc_auth.h new file mode 100644 index 0000000..010a1e2 --- /dev/null +++ b/src/lib/ccapi/include/rpc_auth.h @@ -0,0 +1,71 @@ +/* $Copyright: + * + * Copyright 2004-2006 by the Massachusetts Institute of Technology. + * + * All rights reserved. + * + * Export of this software from the United States of America may require a + * specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute + * this software and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice appear in all + * copies and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of M.I.T. not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Furthermore if you + * modify this software you must label your software as modified software + * and not distribute it in such a fashion that it might be confused with + * the original MIT software. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Individual source code files are copyright MIT, Cygnus Support, + * OpenVision, Oracle, Sun Soft, FundsXpress, and others. + * + * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, + * and Zephyr are trademarks of the Massachusetts Institute of Technology + * (MIT). No commercial use of these trademarks may be made without prior + * written permission of MIT. + * + * "Commercial use" means use of a name in a product or other for-profit + * manner. It does NOT prevent a commercial firm from referring to the MIT + * trademarks in order to convey information (although in doing so, + * recognition of their trademark status should be given). + * $ + */ + + +/* + * Types for RPC auth + session info + * + */ + +#ifndef __RPC_AUTH_H__ +#define __RPC_AUTH_H__ + +#include "CredentialsCache.h" + +/*preliminary*/ +struct cc_auth_info_t { + cc_uint8 *info; + cc_uint32 len; +}; +typedef struct cc_auth_info_t cc_auth_info_t; + +/*preliminary*/ +struct cc_session_info_t { + cc_uint8 *info; + cc_uint32 len; +}; +typedef struct cc_session_info_t cc_session_info_t; + +cc_int32 ccs_rpc_is_authorized(cc_auth_info_t* msg_auth, cc_session_info_t* msg_session, cc_auth_info_t* stored_auth, cc_session_info_t* stored_session, cc_uint32 *authorizedp); + +#endif /*__RPC_AUTH_H__*/ diff --git a/src/lib/ccapi/server/NTMakefile b/src/lib/ccapi/server/NTMakefile index b221bcb..564097c 100644 --- a/src/lib/ccapi/server/NTMakefile +++ b/src/lib/ccapi/server/NTMakefile @@ -1,18 +1,21 @@ -# Makefile for the CCAPI Generic Server +# Makefile for the CCAPI Server Library !INCLUDE -CFLAGS = -I../include +CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsmt) -CCAPI_LIB = ../client/ccapi.lib -WINLIBS = user32.lib advapi32.lib -CCSOBJS = ccs_context.obj ccs_ccache.obj ccs_lists.obj rpc_auth.obj serv_ops.obj +CC_SERVER_OBJS = ccs_context.obj ccs_ccache.obj ccs_lists.obj rpc_auth.obj serv_ops.obj -all: ccapi_server.exe +CC_SERVER_LIB = cc_server.lib -ccapi_server.exe: main.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ main.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +CC_COMMON_LIB = ../common/cc_common.lib + +$(CC_SERVER_LIB): $(CC_SERVER_OBJS) + $(implib) /NOLOGO /OUT:$@ $** + +all: $(CC_SERVER_LIB) clean: - del *.obj *.exe + del *.obj *.lib + \ No newline at end of file diff --git a/src/lib/ccapi/server/datastore.h b/src/lib/ccapi/server/datastore.h deleted file mode 100644 index 4f119f9..0000000 --- a/src/lib/ccapi/server/datastore.h +++ /dev/null @@ -1,189 +0,0 @@ -/* $Copyright: - * - * Copyright 2004-2006 by the Massachusetts Institute of Technology. - * - * All rights reserved. - * - * Export of this software from the United States of America may require a - * specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute - * this software and its documentation for any purpose and without fee is - * hereby granted, provided that the above copyright notice appear in all - * copies and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of M.I.T. not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Furthermore if you - * modify this software you must label your software as modified software - * and not distribute it in such a fashion that it might be confused with - * the original MIT software. M.I.T. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Individual source code files are copyright MIT, Cygnus Support, - * OpenVision, Oracle, Sun Soft, FundsXpress, and others. - * - * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, - * and Zephyr are trademarks of the Massachusetts Institute of Technology - * (MIT). No commercial use of these trademarks may be made without prior - * written permission of MIT. - * - * "Commercial use" means use of a name in a product or other for-profit - * manner. It does NOT prevent a commercial firm from referring to the MIT - * trademarks in order to convey information (although in doing so, - * recognition of their trademark status should be given). - * $ - */ -/* - * Prototypes and data structures for datastore. - * - */ - - -#ifndef __CCDATASTOREH__ -#define __CCDATASTOREH__ - -#include "CredentialsCache.h" -#include "rpc_auth.h" -#include "generic_lists.h" - -enum cc_list_type { - generic = 0, - context, - cache, - credentials -}; - -struct cc_context_iterate_t { - cc_context_list_node_t* next; -}; -typedef struct cc_context_iterate_t cc_context_iterate_t; - -struct cc_ccache_iterate_t { - cc_ccache_list_node_t* next; -}; -typedef struct cc_ccache_iterate_t cc_ccache_iterate_t; - -struct cc_credentials_iterate_t { - cc_credentials_list_node_t* next; -}; -typedef struct cc_credentials_iterate_t cc_credentials_iterate_t; - -struct cc_lock { - cc_uint32 read_locks; /* count of read locks (>= 0) */ - cc_uint32 write_locks; /* count of write locks (0 or 1) */ - void * platform_data; /* platform specific implementation data */ -}; -typedef struct cc_lock cc_lock_t; - - -struct cc_server_context_t { - cc_ccache_list_head_t* ccaches; /*our ccaches*/ - cc_generic_list_head_t* active_iterators; /*active ccache iterators*/ - cc_int32 api_version; /*Version our client passed in on init (ccapi_version_X) */ - cc_auth_info_t* auth_info; /*auth info passed in from RPC*/ - cc_session_info_t* session_info; /*session info passed in from RPC*/ - cc_time64 changed; /*date of last change to this context*/ - cc_int32 error; /*last error code*/ - cc_lock_t locks; /*are we locked?*/ -}; -typedef struct cc_server_context_t cc_server_context_t; - -struct cc_server_ccache_t { - char* name; /*name of this ccache*/ - char* principal_v4; /*v4 principal associated with this cache*/ - char* principal_v5; /*v5 principal associated with this cache*/ - cc_uint32 versions; /*versions of creds supported (from cc_credentials enum in CredentialsCache.h)*/ - cc_time64 changed; /*date of last change to ccache*/ - cc_int32 kdc_set; /*is the KDC time offset initialized?*/ - cc_time64 kdc_offset; /*offset of our clock relative kdc*/ - cc_time64 last_default; /*the last date when we were default*/ - cc_int32 is_default; /*is this the default cred on this ccache?*/ - cc_generic_list_head_t* active_iterators; /*iterators which clients have opened on this cache*/ - cc_credentials_list_head_t* creds; /*list of creds stored in this ccache*/ - cc_server_context_t* mycontext; /*context to which I belong*/ - cc_lock_t locks; /*are we locked?*/ -}; -typedef struct cc_server_ccache_t cc_server_ccache_t; - -struct cc_server_credentials_t { - cc_int32 is_default; /*Are we the default cred? (first in list)*/ - cc_credentials_union creds; -}; -typedef struct cc_server_credentials_t cc_server_credentials_t; - - -/*Note: cci means Credential Cache Internal, to differentiate from exported API macros*/ - -cc_int32 ccs_context_iterate_has_next(struct cc_context_iterate_t *iterate); -cc_int32 ccs_context_iterate_next(struct cc_context_iterate_t *iterate, cc_context_list_node_t**); - -cc_int32 ccs_ccache_iterate_has_next(struct cc_ccache_iterate_t *iterate); -cc_int32 ccs_ccache_iterate_next(struct cc_ccache_iterate_t *iterate, cc_ccache_list_node_t**); - -cc_int32 ccs_credentials_iterate_has_next(cc_credentials_iterate_t *iterate); -cc_int32 ccs_credentials_iterate_next(cc_credentials_iterate_t *iterate, cc_credentials_list_node_t **); - -cc_int32 ccs_context_list_new(cc_context_list_head_t**); -cc_int32 ccs_context_list_append(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**); -cc_int32 ccs_context_list_prepend(cc_context_list_head_t *head, cc_server_context_t *data, cc_context_list_node_t**); -cc_int32 ccs_context_list_remove_element(cc_context_list_head_t* head, cc_context_list_node_t* rem); -cc_int32 ccs_context_list_iterator(cc_context_list_head_t *head, struct cc_context_iterate_t**); -cc_int32 ccs_context_free_iterator(struct cc_context_iterate_t *iterator); -cc_int32 ccs_context_list_destroy(cc_context_list_head_t* head) ; -cc_int32 ccs_context_list_copy(cc_context_list_head_t* head, cc_context_list_head_t**); - -cc_int32 ccs_ccache_list_new(cc_ccache_list_head_t**); -cc_int32 ccs_ccache_list_append(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**); -cc_int32 ccs_ccache_list_prepend(cc_ccache_list_head_t *head, cc_server_ccache_t *data, cc_ccache_list_node_t**); -cc_int32 ccs_ccache_list_remove_element(cc_ccache_list_head_t* head, cc_ccache_list_node_t* rem); -cc_int32 ccs_ccache_list_iterator(cc_ccache_list_head_t *head, struct cc_ccache_iterate_t**); -cc_int32 ccs_ccache_free_iterator(struct cc_ccache_iterate_t *iterator); -cc_int32 ccs_ccache_list_destroy(cc_ccache_list_head_t* head) ; -cc_int32 ccs_ccache_list_copy(cc_ccache_list_head_t* head, cc_ccache_list_head_t**); - - -cc_int32 ccs_credentials_list_new(cc_credentials_list_head_t**); -cc_int32 ccs_credentials_list_append(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**); -cc_int32 ccs_credentials_list_prepend(cc_credentials_list_head_t *head, cc_server_credentials_t *data, cc_credentials_list_node_t**); -cc_int32 ccs_credentials_list_remove_element(cc_credentials_list_head_t* head, cc_credentials_list_node_t* rem); -cc_int32 ccs_credentials_list_iterator(cc_credentials_list_head_t *head, cc_credentials_iterate_t**); -cc_int32 ccs_credentials_free_iterator(cc_credentials_iterate_t* iterator); -cc_int32 ccs_credentials_list_destroy(cc_credentials_list_head_t* head) ; -cc_int32 ccs_credentials_list_copy(cc_credentials_list_head_t* head, cc_credentials_list_head_t**) ; - - -cc_int32 ccs_context_new(int api_version, cc_auth_info_t* auth_info, cc_session_info_t* session_info, cc_server_context_t** ) ; -cc_int32 ccs_context_get_default_ccache_name(cc_server_context_t* ctx, char **); -cc_int32 ccs_context_find_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t**); -cc_int32 ccs_context_open_ccache(cc_server_context_t* ctx, char *name, cc_server_ccache_t** ); -cc_int32 ccs_context_create_ccache(cc_server_context_t* ctx, char *name, int creds_version, char *principal, cc_server_ccache_t**); -cc_int32 ccs_context_create_default_ccache(cc_server_context_t* ctx, int creds_version, char *principal, cc_server_ccache_t**); -cc_int32 ccs_context_ccache_iterator(cc_server_context_t* ctx, cc_ccache_iterate_t**); -cc_int32 ccs_context_compare(cc_server_context_t* a, cc_server_context_t* b); -cc_int32 ccs_context_destroy(cc_server_context_t* ctx); -cc_int32 ccs_context_rem_ccache(cc_server_context_t* ctx, cc_server_ccache_t* ccache); - -cc_int32 ccs_ccache_new(char *name, char *principal, int cred_vers, cc_server_ccache_t**); -cc_int32 ccs_ccache_check_version(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat); -cc_int32 ccs_ccache_check_principal(const cc_server_ccache_t *ccache, const cc_credentials_union* creds, cc_uint32* compat); -cc_int32 ccs_ccache_store_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials); -cc_int32 ccs_ccache_rem_creds(cc_server_ccache_t *ccache, const cc_credentials_union* credentials); -cc_int32 ccs_ccache_move(cc_server_ccache_t *source, cc_server_ccache_t* destination); -cc_int32 ccs_ccache_get_kdc_time_offset(cc_server_ccache_t* ccache, cc_time64* offset); -cc_int32 ccs_ccache_set_kdc_time_offset(cc_server_ccache_t* ccache, cc_time64 offset); -cc_int32 ccs_ccache_clear_kdc_time_offset(cc_server_ccache_t* ccache); -cc_int32 ccs_ccache_new_iterator(cc_server_ccache_t* ccache, cc_credentials_iterate_t** iterator); -cc_int32 ccs_ccache_get_principal(cc_server_ccache_t* ccache, cc_int32 version, char ** principal); -cc_int32 ccs_ccache_set_principal(cc_server_ccache_t* ccache, cc_int32 version, char * principal); -cc_int32 ccs_ccache_free_principal(char * principal); -cc_int32 ccs_ccache_destroy(cc_server_ccache_t* ccache); -void ccs_ccache_changed(cc_server_ccache_t* ccache); -cc_int32 ccs_ccache_compare(cc_server_ccache_t* ccache1, cc_server_ccache_t* ccache2, cc_uint32 *result); -#endif /*__CCDATASTOREH__*/ diff --git a/src/lib/ccapi/server/rpc_auth.h b/src/lib/ccapi/server/rpc_auth.h deleted file mode 100644 index 010a1e2..0000000 --- a/src/lib/ccapi/server/rpc_auth.h +++ /dev/null @@ -1,71 +0,0 @@ -/* $Copyright: - * - * Copyright 2004-2006 by the Massachusetts Institute of Technology. - * - * All rights reserved. - * - * Export of this software from the United States of America may require a - * specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute - * this software and its documentation for any purpose and without fee is - * hereby granted, provided that the above copyright notice appear in all - * copies and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of M.I.T. not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Furthermore if you - * modify this software you must label your software as modified software - * and not distribute it in such a fashion that it might be confused with - * the original MIT software. M.I.T. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Individual source code files are copyright MIT, Cygnus Support, - * OpenVision, Oracle, Sun Soft, FundsXpress, and others. - * - * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, - * and Zephyr are trademarks of the Massachusetts Institute of Technology - * (MIT). No commercial use of these trademarks may be made without prior - * written permission of MIT. - * - * "Commercial use" means use of a name in a product or other for-profit - * manner. It does NOT prevent a commercial firm from referring to the MIT - * trademarks in order to convey information (although in doing so, - * recognition of their trademark status should be given). - * $ - */ - - -/* - * Types for RPC auth + session info - * - */ - -#ifndef __RPC_AUTH_H__ -#define __RPC_AUTH_H__ - -#include "CredentialsCache.h" - -/*preliminary*/ -struct cc_auth_info_t { - cc_uint8 *info; - cc_uint32 len; -}; -typedef struct cc_auth_info_t cc_auth_info_t; - -/*preliminary*/ -struct cc_session_info_t { - cc_uint8 *info; - cc_uint32 len; -}; -typedef struct cc_session_info_t cc_session_info_t; - -cc_int32 ccs_rpc_is_authorized(cc_auth_info_t* msg_auth, cc_session_info_t* msg_session, cc_auth_info_t* stored_auth, cc_session_info_t* stored_session, cc_uint32 *authorizedp); - -#endif /*__RPC_AUTH_H__*/ diff --git a/src/lib/ccapi/unit-test/NTMakefile b/src/lib/ccapi/unit-test/NTMakefile index eb2fd53..9bb486b 100644 --- a/src/lib/ccapi/unit-test/NTMakefile +++ b/src/lib/ccapi/unit-test/NTMakefile @@ -1,30 +1,48 @@ -# Makefile for the CCAPI Generic Server +!include -!INCLUDE +CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsmt) -CFLAGS = -I../include +WINLIBS = ws2_32.lib rpcrt4.lib $(guilibsdll) -CCAPI_LIB = ../lib/ccapi.lib -WINLIBS = user32.lib advapi32.lib -CCSOBJS = context.obj ccache.obj lists.obj rpc_auth.obj serv_ops.obj +T_CCACHE = t_ccache.exe -all: t_lists.exe t_msg.exe t_ccache.exe t_context.exe ccapi_server.exe +T_CONTEXT = t_context.exe -t_lists.exe: t_lists.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ t_lists.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +T_LISTS = t_lists.exe -t_msg.exe: t_msg.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ t_msg.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +T_MSG = t_msg.exe -t_ccache.exe: t_ccache.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ t_ccache.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +T_SERVER = t_server.exe -t_context.exe: t_context.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ t_context.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +all: $(T_CCACHE) $(T_CONTEXT) $(T_LISTS) $(T_MSG) $(T_SERVER) -ccapi_server.exe: main.obj $(CCSOBJS) $(CCAPI_LIB) - link -out:$@ main.obj $(CCSOBJS) $(CCAPI_LIB) $(WINLIBS) +ntccrpc_c.c ntccrpc_s.c ntccrpc.h: ntccrpc.idl ntccrpc.acf + midl ntccrpc.idl /acf ntccrpc.acf + +CC_CLIENT_LIB = ..\client\cc_client.lib + +CC_COMMON_LIB = ..\common\cc_common.lib + +CC_SERVER_LIB = ..\server\cc_server.lib + +CC_API_LIB = ..\windows\krbcc32.lib + +$(T_CCACHE): t_ccache.obj $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +$(T_CONTEXT): t_context.obj $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +$(T_LISTS): t_lists.obj $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +$(T_MSG): t_msg.obj $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +$(T_SERVER): t_server.obj $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +clean: + del *.exe *.dll *.lib *.exp *.obj ntccrpc_c.c ntccrpc_s.c ntccrpc.h -clean: - del *.obj *.exe diff --git a/src/lib/ccapi/unit-test/t_ccache.c b/src/lib/ccapi/unit-test/t_ccache.c index 6ef33ea..175764e 100644 --- a/src/lib/ccapi/unit-test/t_ccache.c +++ b/src/lib/ccapi/unit-test/t_ccache.c @@ -59,8 +59,8 @@ int main() { int i; cc_int32 code; - code = cci_ccache_new("The first", p1, cc_credentials_v4_v5, &c1); - code = cci_ccache_new("The 2nd", p2, cc_credentials_v4_v5, &c2); + code = ccs_ccache_new("The first", p1, cc_credentials_v4_v5, &c1); + code = ccs_ccache_new("The 2nd", p2, cc_credentials_v4_v5, &c2); cred1 = (cc_server_credentials_t*)malloc(sizeof(cc_server_credentials_t)); memset(cred1,0,sizeof(cc_server_credentials_t)); @@ -83,30 +83,30 @@ int main() { strncpy(cred2->creds.credentials.credentials_v4->principal, p1, strlen(p1)); cred3->creds.credentials.credentials_v5->client = p1; - code = cci_ccache_store_creds(c1, &cred1->creds); + code = ccs_ccache_store_creds(c1, &cred1->creds); printf("(c1, cred1) -> %d\n",code); - code = cci_ccache_store_creds(c1, &cred2->creds); + code = ccs_ccache_store_creds(c1, &cred2->creds); printf("(c1, cred2) -> %d\n",code); - code = cci_ccache_store_creds(c2, &cred3->creds); + code = ccs_ccache_store_creds(c2, &cred3->creds); printf("(c2, cred3) -> %d\n",code); - code = cci_ccache_store_creds(c1, &cred3->creds); + code = ccs_ccache_store_creds(c1, &cred3->creds); printf("(c1, cred3) -> %d\n",code); i = 0; - code = cci_ccache_move(c1, c2); - code = cci_ccache_destroy(c1); - code = cci_ccache_new_iterator(c2, &iterator); - while (cci_credentials_iterate_has_next(iterator)) { + code = ccs_ccache_move(c1, c2); + code = ccs_ccache_destroy(c1); + code = ccs_ccache_new_iterator(c2, &iterator); + while (ccs_credentials_iterate_has_next(iterator)) { i++; - code = cci_credentials_iterate_next(iterator, &node); + code = ccs_credentials_iterate_next(iterator, &node); stored_cred = (cc_server_credentials_t *)node->data; printf("%d %d %s\n", stored_cred->is_default, stored_cred->creds.version, stored_cred->creds.credentials.credentials_v4->principal); if (i == 1) { - code = cci_ccache_rem_creds(c2,&cred2->creds); + code = ccs_ccache_rem_creds(c2,&cred2->creds); printf("(c2 rem cred2) -> %d\n",code); } } diff --git a/src/lib/ccapi/unit-test/t_context.c b/src/lib/ccapi/unit-test/t_context.c index 9e35d9a..d76ff78 100644 --- a/src/lib/ccapi/unit-test/t_context.c +++ b/src/lib/ccapi/unit-test/t_context.c @@ -68,10 +68,10 @@ int main() { int i; cc_int32 code; - code = cci_context_new(5, auth_info, session_info, &ctx); - code = cci_context_create_default_ccache(ctx, cc_credentials_v4, "Spike", &ccache); - code = cci_context_get_default_ccache_name(ctx, &name); - code = cci_context_open_ccache(ctx, name, &ccache); + code = ccs_context_new(5, auth_info, session_info, &ctx); + code = ccs_context_create_default_ccache(ctx, cc_credentials_v4, "Spike", &ccache); + code = ccs_context_get_default_ccache_name(ctx, &name); + code = ccs_context_open_ccache(ctx, name, &ccache); for (i = 0; i < 5; i++) { creds = (cc_credentials_union*)malloc(sizeof(cc_credentials_union)); @@ -79,32 +79,32 @@ int main() { creds->credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t)); strcpy(creds->credentials.credentials_v4->principal, "Spike"); - code = cci_ccache_store_creds(ccache, creds); + code = ccs_ccache_store_creds(ccache, creds); } - code = cci_context_create_ccache(ctx, "ccache 2", cc_credentials_v4, "Jeff", &ccache); - code = cci_context_open_ccache(ctx, "ccache 2", &ccache); + code = ccs_context_create_ccache(ctx, "ccache 2", cc_credentials_v4_v5, "Jeff", &ccache); + code = ccs_context_open_ccache(ctx, "ccache 2", &ccache); for (i = 0; i < 5; i++) { creds = (cc_credentials_union*)malloc(sizeof(cc_credentials_union)); - creds->version = cc_credentials_v4; - creds->credentials.credentials_v4 = (cc_credentials_v4_t*)malloc(sizeof(cc_credentials_v4_t)); - strcpy(creds->credentials.credentials_v4->principal, "Jeff"); + creds->version = cc_credentials_v5; + creds->credentials.credentials_v5 = (cc_credentials_v5_t*)malloc(sizeof(cc_credentials_v5_t)); + strcpy(creds->credentials.credentials_v5->principal, "Jeff"); - cci_ccache_store_creds(ccache, creds); + ccs_ccache_store_creds(ccache, creds); } - code = cci_context_ccache_iterator(ctx, &ccache_iterator); - while (cci_ccache_iterate_has_next(ccache_iterator)) { - code = cci_ccache_iterate_next(ccache_iterator, &ccache_node); + code = ccs_context_ccache_iterator(ctx, &ccache_iterator); + while (ccs_ccache_iterate_has_next(ccache_iterator)) { + code = ccs_ccache_iterate_next(ccache_iterator, &ccache_node); ccache = (cc_server_ccache_t *)ccache_node->data; printf("%x for %s %s default = %d v %d\n", ccache, ccache->principal_v4, ccache->principal_v5, ccache->is_default, ccache->versions); - code = cci_ccache_new_iterator(ccache, &creds_iterator); - while (cci_credentials_iterate_has_next(creds_iterator)) { - code = cci_credentials_iterate_next(creds_iterator, &creds_node); + code = ccs_ccache_new_iterator(ccache, &creds_iterator); + while (ccs_credentials_iterate_has_next(creds_iterator)) { + code = ccs_credentials_iterate_next(creds_iterator, &creds_node); server_creds = (cc_server_credentials_t *)creds_node->data; printf("\t%s %d\n", server_creds->creds.credentials.credentials_v4->principal, diff --git a/src/lib/ccapi/unit-test/t_server.c b/src/lib/ccapi/unit-test/t_server.c index d4d9984..d609394 100644 --- a/src/lib/ccapi/unit-test/t_server.c +++ b/src/lib/ccapi/unit-test/t_server.c @@ -143,7 +143,7 @@ main(void) cc_session_info_t * session_info; cc_int32 code; - if ( cci_serv_initialize() != ccNoError ) + if ( ccs_serv_initialize() != ccNoError ) return 1; while ( 1 ) { @@ -163,7 +163,7 @@ main(void) code = obtain_session_info(&session_info); /* process message */ - code = cci_serv_process_msg(msg, auth_info, session_info, &resp); + code = ccs_serv_process_msg(msg, auth_info, session_info, &resp); /* flatten response */ code = cci_msg_flatten(resp, NULL); diff --git a/src/lib/ccapi/windows/NTMakefile b/src/lib/ccapi/windows/NTMakefile new file mode 100644 index 0000000..f6fee6f --- /dev/null +++ b/src/lib/ccapi/windows/NTMakefile @@ -0,0 +1,35 @@ +!include + +CFLAGS = -I../include $(cdebug) $(cflags) $(cvarsmt) + +CCAPI_SERVER = ccapi_server.exe + +CCAPI_DLLFILE = krbcc32.dll + +WINLIBS = ws2_32.lib rpcrt4.lib $(guilibsdll) + +all: $(CCAPI_DLLFILE) $(CCAPI_SERVER) + +ntccrpc_c.c ntccrpc_s.c ntccrpc.h: ntccrpc.idl ntccrpc.acf + midl ntccrpc.idl /acf ntccrpc.acf + +CLIENT_OBJS = ntccrpc_c.obj client.obj dllmain.obj + +SERVER_OBJS = ntccrpc_s.obj server.obj + +CC_CLIENT_LIB = ..\client\cc_client.lib + +CC_COMMON_LIB = ..\common\cc_common.lib + +CC_SERVER_LIB = ..\server\cc_server.lib + +$(CCAPI_DLLFILE): $(CLIENT_OBJS) $(CC_CLIENT_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO /OUT:$@ $(ldebug) $(dlllflags) $(guilibsmt) -def:cacheapi.def $** $(WINLIBS) + +$(CCAPI_SERVER): $(SERVER_OBJS) $(CC_SERVER_LIB) $(CC_COMMON_LIB) + $(link) /NOLOGO $(conlibsmt) $(ldebug) $(conlflags) /OUT:$@ $** $(WINLIBS) + +clean: + del *.exe *.dll *.lib *.exp *.obj ntccrpc_c.c ntccrpc_s.c ntccrpc.h + + diff --git a/src/lib/ccapi/windows/cacheapi.def b/src/lib/ccapi/windows/cacheapi.def new file mode 100644 index 0000000..c54cc11 --- /dev/null +++ b/src/lib/ccapi/windows/cacheapi.def @@ -0,0 +1,29 @@ +EXPORTS + ; ccapi v3 only exports one function + cc_initialize @14 + + ; ccapi v2 compatibility functions + cc_close @2 + cc_create @3 + cc_destroy @4 + cc_free_NC_info @5 + cc_free_creds @6 + cc_free_name @7 + cc_free_principal @8 + cc_get_NC_info @9 + cc_get_change_time @10 + cc_get_cred_version @11 + cc_get_name @12 + cc_get_principal @13 + cc_lock_request @15 + cc_open @16 + cc_remove_cred @17 + cc_seq_fetch_NCs_begin @18 + cc_seq_fetch_NCs_end @19 + cc_seq_fetch_NCs_next @20 + cc_seq_fetch_creds_begin @21 + cc_seq_fetch_creds_end @22 + cc_seq_fetch_creds_next @23 + cc_set_principal @24 + cc_shutdown @25 + cc_store @26 diff --git a/src/lib/ccapi/windows/client.c b/src/lib/ccapi/windows/client.c new file mode 100644 index 0000000..db0b63a --- /dev/null +++ b/src/lib/ccapi/windows/client.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include "ntccrpc.h" +#include +#include "CredentialsCache.h" +#include "msg.h" + +static RPC_BINDING_HANDLE hRpcBinding; + +void * __RPC_USER MIDL_user_allocate(size_t s) { + return malloc(s); +} + +void __RPC_USER MIDL_user_free(void * p) { + free(p); +} + +int cc_rpc_init(void) { + RPC_STATUS status; + TCHAR * bindstring = NULL; + RPC_SECURITY_QOS sqos; + + status = RpcStringBindingCompose(NULL, + _T("ncalrpc"), + NULL, + NULL, + NULL, + &bindstring); + + if (status != RPC_S_OK) { + fprintf(stderr, "RpcStringBindingCompose failed: %d\n", + status); + return 1; + } + + status = RpcBindingFromStringBinding(bindstring, + &hRpcBinding); + + if (status != RPC_S_OK) { + fprintf(stderr, "RpcBindingFromStringBinding failed: %d\n", + status); + return 1; + } + + status = RpcStringFree(&bindstring); + + ZeroMemory(&sqos, sizeof(sqos)); + + sqos.Version = 1; + sqos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; + sqos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; + sqos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; + + status = RpcBindingSetAuthInfoEx(hRpcBinding, + NULL, + RPC_C_AUTHN_LEVEL_CALL, + RPC_C_AUTHN_WINNT, + NULL, + 0, + &sqos); + if (status != RPC_S_OK) { + fprintf(stderr, "RpcBindingSetAuthInfoEx failed: %d\n", + status); + return 1; + } + + return 0; +} + +int cc_rpc_cleanup(void) { + RPC_STATUS status; + + status = RpcBindingFree(&hRpcBinding); + + return 0; +} + +cc_int32 cci_set_thread_session_id(unsigned char * client_name, LUID luid) { + +} + +void cci_get_thread_session_id(unsigned char * client_name, int len, LUID *pluid) { + +} + + +/* __int32 ccapi_Message( + * [in] handle_t h, + * [string][in] unsigned char *client_name, + * [in] struct _LUID luid, + * [in] __int32 cb_buffer, + * [out] __int32 *cb_len, + * [size_is][string][out] unsigned char buffer[ ]); + */ + +cc_int32 cci_perform_rpc(cc_msg_t *request, cc_msg_t **response) +{ + __int32 rpc_code; + unsigned char client_name[256]; + LUID luid; + struct __LUID __luid; + unsigned char out_buf[MAXMSGLEN]; + __int32 out_len = MAXMSGLEN; + + if (!cc_rpc_init()) + return -1; + + cci_get_thread_session_id(client_name, sizeof(client_name), &luid); + + __luid.HighPart = luid.HighPart; + __luid.LowPart = luid.LowPart; + + rpc_code = ccapi_Message(hRpcBinding, client_name, __luid, + request->flat, request->flat_len, + out_buf, &out_len); + + return rpc_code; +} diff --git a/src/lib/ccapi/windows/dllmain.c b/src/lib/ccapi/windows/dllmain.c new file mode 100644 index 0000000..6b4d6bf --- /dev/null +++ b/src/lib/ccapi/windows/dllmain.c @@ -0,0 +1,15 @@ +#include + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, + LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + default: + return TRUE; + } +} + diff --git a/src/lib/ccapi/windows/ntccrpc.acf b/src/lib/ccapi/windows/ntccrpc.acf new file mode 100644 index 0000000..77216a9 --- /dev/null +++ b/src/lib/ccapi/windows/ntccrpc.acf @@ -0,0 +1,8 @@ +[ + explicit_handle +] + +interface portable_ccapi +{ + +} \ No newline at end of file diff --git a/src/lib/ccapi/windows/ntccrpc.idl b/src/lib/ccapi/windows/ntccrpc.idl new file mode 100644 index 0000000..0dd038f --- /dev/null +++ b/src/lib/ccapi/windows/ntccrpc.idl @@ -0,0 +1,31 @@ +[ + uuid(c8b4a635-e9e4-4650-a073-b25610324950), + version(1.0), + endpoint("ncalrpc:[mit_nt_ccapi]"), + pointer_default(unique) +] + +interface portable_ccapi +{ + const short MAXMSGLEN = 65536; + + // Locally Unique Identifier + // + + struct __LUID { + __int32 LowPart; + long HighPart; + }; + + + // The Generic CCAPI Message RPC + + __int32 ccapi_Message ( + [in] handle_t h, + [in, string] unsigned char * client_name, + [in] struct __LUID luid, + [in, length_is(in_len), size_is(MAXMSGLEN)] unsigned char in_buf[], + [in] __int32 in_len, + [out, length_is(*out_len), size_is(MAXMSGLEN)] unsigned char out_buf[], + [out] __int32 * out_len); +} diff --git a/src/lib/ccapi/windows/server.c b/src/lib/ccapi/windows/server.c new file mode 100644 index 0000000..5ce8e6e --- /dev/null +++ b/src/lib/ccapi/windows/server.c @@ -0,0 +1,638 @@ + + +#include +#include "msg.h" +#include "marshall.h" +#include "serv_ops.h" +#include "datastore.h" +#include +#include +#include +#include +#include +#include "ntccrpc.h" +#include + +#define SVCNAME "MIT_CCAPI_NT_Service" + +SERVICE_STATUS_HANDLE h_service_status = NULL; +SERVICE_STATUS service_status; +FILE * logfile = NULL; + +/* Log File */ +void begin_log(void) { + char temppath[512]; + + temppath[0] = L'\0'; + + GetTempPathA(sizeof(temppath), temppath); + StringCbCatA(temppath, sizeof(temppath), "mit_nt_ccapi.log"); + logfile = fopen(temppath, "w"); +} + +void end_log(void) { + if (logfile) { + fclose(logfile); + logfile = NULL; + } +} + +BOOL report_status(DWORD state, + DWORD exit_code, + DWORD wait_hint) { + static DWORD checkpoint = 1; + BOOL rv = TRUE; + + if (state == SERVICE_START_PENDING) + service_status.dwControlsAccepted = 0; + else + service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + service_status.dwCurrentState = state; + service_status.dwWin32ExitCode = exit_code; + service_status.dwWaitHint = wait_hint; + + if (state == SERVICE_RUNNING || + state == SERVICE_STOPPED) + service_status.dwCheckPoint = 0; + else + service_status.dwCheckPoint = checkpoint++; + + rv = SetServiceStatus(h_service_status, &service_status); + + return rv; +} + +void service_start(DWORD argc, LPTSTR * argv) { + RPC_STATUS status; + RPC_BINDING_VECTOR * bv; + + status = RpcServerUseProtseq("ncalrpc", + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + NULL); + + if (status != RPC_S_OK) { + return; + } + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerRegisterIf(portable_ccapi_v1_0_s_ifspec, + 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerInqBindings(&bv); + + if (status != RPC_S_OK) + return; + + status = RpcEpRegister(portable_ccapi_v1_0_s_ifspec, + bv, 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerRegisterAuthInfo(NULL, + RPC_C_AUTHN_WINNT, + 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerListen(1, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, + TRUE); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_RUNNING, NO_ERROR, 0); + + begin_log(); + + status = RpcMgmtWaitServerListen(); + + end_log(); + + RpcEpUnregister(portable_ccapi_v1_0_s_ifspec, bv, 0); + + RpcBindingVectorFree(&bv); +} + +void service_stop(void) { + RpcMgmtStopServerListening(0); +} + +void * __RPC_USER MIDL_user_allocate(size_t s) { + return malloc(s); +} + +void __RPC_USER MIDL_user_free(void * p) { + free(p); +} + +typedef struct tag_client_info { + char client_name[512]; + LUID luid; +} client_info_t; + +int obtain_auth_info(client_info_t * client_info, cc_auth_info_t ** pauth_info) +{ + *pauth_info = (cc_auth_info_t *)malloc(sizeof(cc_auth_info_t)); + if ( !*pauth_info ) + return ccErrNoMem; + + (*pauth_info)->len = strlen(client_info->client_name) + 1; + (*pauth_info)->info = malloc((*pauth_info)->len); + if ( !(*pauth_info)->info ) { + free(*pauth_info); + return ccErrNoMem; + } + + memcpy((*pauth_info)->info, client_info->client_name, (*pauth_info)->len); + + return 0; +} + +void destroy_auth_info(cc_auth_info_t *auth_info) +{ + free(auth_info->info); + free(auth_info); +} + +int obtain_session_info(client_info_t * client_info, cc_session_info_t ** psession_info) +{ + *psession_info = (cc_session_info_t *)malloc(sizeof(cc_session_info_t)); + if ( !*psession_info ) + return ccErrNoMem; + + (*psession_info)->len = sizeof(LUID); + (*psession_info)->info = malloc((*psession_info)->len); + if ( !(*psession_info)->info ) { + free(*psession_info); + return ccErrNoMem; + } + + memcpy((*psession_info)->info, &client_info->luid, (*psession_info)->len); + + return 0; +} + +void destroy_session_info(cc_session_info_t *session_info) +{ + free(session_info->info); + free(session_info); +} + +RPC_STATUS check_auth(handle_t h, client_info_t * client_info) { + RPC_BINDING_HANDLE bh = (RPC_BINDING_HANDLE) h; + RPC_STATUS status; + HANDLE htoken = NULL; + char name[256]; + char domain[256]; + DWORD name_len; + DWORD domain_len; + SID_NAME_USE snu = 0; + + struct { + TOKEN_ORIGIN origin; + char pad[512]; + } torigin; + + struct { + TOKEN_OWNER owner; + char pad[4096]; + } towner; + + DWORD len; + + status = RpcImpersonateClient(bh); + + if (status != RPC_S_OK) + return status; + + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_READ | TOKEN_QUERY_SOURCE, + FALSE, + &htoken)) { + status = GetLastError(); + goto _cleanup; + } + + len = 0; + + if (!GetTokenInformation(htoken, + TokenOrigin, + &torigin.origin, + sizeof(torigin), + &len)) { + status = GetLastError(); + goto _cleanup; + } + + if (!GetTokenInformation(htoken, + TokenOwner, + &towner.owner, + sizeof(towner), + &len)) { + status = GetLastError(); + goto _cleanup; + } + + + name_len = sizeof(name)/sizeof(name[0]); + domain_len = sizeof(domain)/sizeof(domain[0]); + + if (!LookupAccountSidA(NULL, + towner.owner.Owner, + name, + &name_len, + domain, + &domain_len, + &snu)) { + status = GetLastError(); + goto _cleanup; + } + + client_info->luid = torigin.origin.OriginatingLogonSession; + StringCbPrintfA(client_info->client_name, + sizeof(client_info->client_name), + "%s\\%s", domain, name); + + status = 0; + + _cleanup: + + RpcRevertToSelf(); + + return status; +} + +__int32 ccapi_Message( + /* [in] */ handle_t h, + /* [string][in] */ unsigned char *client_name, + /* [in] */ struct __LUID luid, + /* [size_is][length_is][in] */ unsigned char in_buf[], + /* [in] */ __int32 in_len, + /* [size_is][length_is][out] */ unsigned char out_buf[], + /* [out] */ __int32 *out_len) +{ + client_info_t client_info; + cc_msg_t * msg; + cc_msg_t * resp; + cc_auth_info_t * auth_info; + cc_session_info_t * session_info; + cc_int32 code; + + if ( ccs_serv_initialize() != ccNoError ) { + code = ccErrServerUnavailable; + goto done; + } + + code = check_auth(h, &client_info); + if (code == 0) { + if (!strcmp("SYSTEM",client_info.client_name) && + client_info.luid.HighPart == 0 && + client_info.luid.LowPart == 0 && + client_name != NULL && + client_name[0] != '\0') { + StringCbPrintfA(client_info.client_name, + sizeof(client_info.client_name), + "%s", client_name); + client_info.luid.HighPart = luid.HighPart; + client_info.luid.LowPart = luid.LowPart; + } + } else { + code = ccErrServerCantBecomeUID; + goto done; + } + + /* allocate message */ + msg = (cc_msg_t *)malloc(sizeof(cc_msg_t)); + if (!msg) { + code = ccErrNoMem; + goto done; + } + + /* unflatten message */ + code = cci_msg_unflatten(in_buf, in_len, &msg); + if (code) + goto cleanup; + + /* obtain auth info */ + code = obtain_auth_info(&client_info, &auth_info); + if (code) + goto cleanup; + + /* obtain session info */ + code = obtain_session_info(&client_info, &session_info); + if (code) + goto cleanup; + + /* process message */ + code = ccs_serv_process_msg(msg, auth_info, session_info, &resp); + if (code) + goto cleanup; + + /* flatten response */ + code = cci_msg_flatten(resp, NULL); + if (code) + goto cleanup; + + /* send response */ + if (resp->flat_len > MAXMSGLEN) { + code = ccErrBadInternalMessage; + goto cleanup; + } + memcpy(out_buf, resp->flat, resp->flat_len); + *out_len = resp->flat_len; + code = ccNoError; + + cleanup: + if (auth_info) + destroy_auth_info(auth_info); + + if (session_info) + destroy_session_info(session_info); + + /* free message */ + if (msg) + cci_msg_destroy(msg); + + /* free response */ + if (resp) + cci_msg_destroy(resp); + + done: + return code ? -1 : 0; +} + +void WINAPI service_control(DWORD ctrl_code) { + switch(ctrl_code) { + case SERVICE_CONTROL_STOP: + report_status(SERVICE_STOP_PENDING, NO_ERROR, 0); + service_stop(); + return; + + /* everything else falls through */ + } + + report_status(service_status.dwCurrentState, NO_ERROR, 0); +} + +void WINAPI service_main(DWORD argc, LPTSTR * argv) { + + h_service_status = RegisterServiceCtrlHandler( _T(SVCNAME), service_control); + + if (!h_service_status) + goto cleanup; + + ZeroMemory(&service_status, sizeof(service_status)); + + service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + service_status.dwServiceSpecificExitCode = 0; + + if (!report_status(SERVICE_START_PENDING, + NO_ERROR, + 3000)) + goto cleanup; + + service_start(argc, argv); + + cleanup: + + if (h_service_status) { + report_status(SERVICE_STOPPED, NO_ERROR, 0); + } +} + + +BOOL +IsInstalled() +{ + BOOL bResult = FALSE; + SC_HANDLE hSCM; + SC_HANDLE hService; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (hSCM) { + + // Try to open the service + hService = OpenService( hSCM, + SVCNAME, + SERVICE_QUERY_CONFIG); + if (hService) { + bResult = TRUE; + CloseServiceHandle(hService); + } + + CloseServiceHandle(hSCM); + } + + return bResult; +} + +BOOL +Install() +{ + char szFilePath[_MAX_PATH]; + SC_HANDLE hSCM; + SC_HANDLE hService; + TCHAR szKey[256]; + HKEY hKey = NULL; + DWORD dwData; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (!hSCM) + return FALSE; + + // Get the executable file path + GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); + + // Create the service + hService = CreateService( hSCM, + SVCNAME, + SVCNAME, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, // start condition + SERVICE_ERROR_NORMAL, + szFilePath, + NULL, + NULL, + NULL, + NULL, + NULL); + if (!hService) { + CloseServiceHandle(hSCM); + return FALSE; + } + + // make registry entries to support logging messages + // Add the source name as a subkey under the Application + // key in the EventLog service portion of the registry. + StringCbCopyA(szKey, 256, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\IKSD"); + if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return FALSE; + } + + // Add the Event ID message-file name to the 'EventMessageFile' subkey. + RegSetValueEx( hKey, + "EventMessageFile", + 0, + REG_EXPAND_SZ, + (CONST BYTE*)szFilePath, + strlen(szFilePath) + 1); + + // Set the supported types flags. + dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + RegSetValueEx( hKey, + "TypesSupported", + 0, + REG_DWORD, + (CONST BYTE*)&dwData, + sizeof(DWORD)); + RegCloseKey(hKey); + + // LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, SVCNAME); + + // tidy up + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return TRUE; +} + +BOOL +Uninstall() +{ + BOOL bResult = FALSE; + SC_HANDLE hService; + SC_HANDLE hSCM; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (!hSCM) + return FALSE; + + hService = OpenService( hSCM, + _T(SVCNAME), + DELETE); + if (hService) { + if (DeleteService(hService)) { + // LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, SVCNAME); + bResult = TRUE; + } else { + // LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, SVCNAME); + } + CloseServiceHandle(hService); + } + + CloseServiceHandle(hSCM); + return bResult; +} + + +// Returns TRUE if it found an arg it recognised, FALSE if not +// Note: processing some arguments causes output to stdout to be generated. +BOOL +ParseStandardArgs(int argc, char* argv[]) +{ + char szFilePath[_MAX_PATH]="not a file name"; + + // See if we have any command line args we recognize + if (argc <= 1) + return FALSE; + + if ( _stricmp(argv[1], "-h") == 0 || + _stricmp(argv[1], "-?") == 0 || + _stricmp(argv[1], "/h") == 0 || + _stricmp(argv[1], "/?") == 0) { + + // + GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath)); + fprintf(stderr, "usage: %s [-v | -i | -u | -h]\r\n",szFilePath); + return TRUE; + } else if (_stricmp(argv[1], "-v") == 0 || + _stricmp(argv[1], "/v") == 0 ) { + + // Spit out version info + fprintf(stderr, "%s Version 0.1\n",_T(SVCNAME)); + fprintf(stderr, "The service is %s installed\n", + IsInstalled() ? "currently" : "not"); + return TRUE; // say we processed the argument + + } else if (_stricmp(argv[1], "-i") == 0 || + _stricmp(argv[1], "/i") == 0) { + + // Request to install. + if (IsInstalled()) { + fprintf(stderr, "%s is already installed\n", _T(SVCNAME)); + } else { + // Try and install the copy that's running + if (Install()) { + fprintf(stderr, "%s installed\n", _T(SVCNAME)); + } else { + fprintf(stderr, "%s failed to install. Error %d\n", _T(SVCNAME), GetLastError()); + } + } + return TRUE; // say we processed the argument + + } else if (_stricmp(argv[1], "-u") == 0 || + _stricmp(argv[1], "/u") == 0) { + + // Request to uninstall. + if (!IsInstalled()) { + fprintf(stderr, "%s is not installed\n", _T(SVCNAME)); + } else { + // Try and remove the copy that's installed + if (Uninstall()) { + // Get the executable file path + GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath)); + fprintf(stderr, "%s removed. (You must delete the file (%s) yourself.)\n", + _T(SVCNAME), szFilePath); + } else { + fprintf(stderr, "Could not remove %s. Error %d\n", _T(SVCNAME), GetLastError()); + } + } + return TRUE; // say we processed the argument + + } + + // Don't recognise the args + return FALSE; +} + +int main(int argc, char ** argv) { + + SERVICE_TABLE_ENTRY dispatch_table[] = { + { _T(SVCNAME), (LPSERVICE_MAIN_FUNCTION) service_main }, + { NULL, NULL } + }; + + if ( ParseStandardArgs(argc, argv) ) + return 0; + + if (!StartServiceCtrlDispatcher(dispatch_table)) { + fprintf(stderr, "Can't start service control dispatcher\n"); + } + + return 0; +} -- cgit v1.1