X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/9244c49f749a0d8a6255c976b84a9127777efea7..9f2c8cb950fea61c599edeb9721aca66f4bd61f6:/openssh/ssh-globus-usage.c diff --git a/openssh/ssh-globus-usage.c b/openssh/ssh-globus-usage.c new file mode 100644 index 0000000..3e30504 --- /dev/null +++ b/openssh/ssh-globus-usage.c @@ -0,0 +1,386 @@ +/* + * Copyright 2009 The Board of Trustees of the University + * of Illinois. See the LICENSE file for detailed license information. + * + * Portions, specifically log_usage_stats(), ssh_usage_stats_init(), + * ssh_usage_stats_close(), ssh_usage_ent_s, ssh_usage_tag_e and + * TAG #defines were based on those from Usage Metrics portions of: + * gridftp/server/source/globus_i_gfs_log.c + * + * Copyright 1999-2006 University of Chicago + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "log.h" +#include "ssh-globus-usage.h" + +#ifdef HAVE_GLOBUS_USAGE + +static globus_list_t *usage_handle_list = NULL; + +#define SSH_GLOBUS_USAGE_ID 12 +#define SSH_GLOBUS_USAGE_VER 0 + +#define SSH_GLOBUS_DEFAULT_TAGLIST "VvMm" +#define SSH_GLOBUS_ALL_TAGLIST "VvMmIuU" +#define SSH_GLOBUS_TAGCOUNT 25 + +typedef enum ssh_usage_tag_e +{ + SSH_GLOBUS_USAGE_SSH_VER = 'V', + SSH_GLOBUS_USAGE_SSL_VER = 'v', + SSH_GLOBUS_USAGE_METHOD = 'M', + SSH_GLOBUS_USAGE_MECHANISM = 'm', + SSH_GLOBUS_USAGE_CLIENTIP = 'I', + SSH_GLOBUS_USAGE_USERNAME = 'u', + SSH_GLOBUS_USAGE_USERDN = 'U' + /* !! ADD to ALL_TAGLIST above and to globus_usage_stats_send() + invocation below when adding here */ +} ssh_usage_tag_t; + +typedef struct ssh_usage_ent_s +{ + globus_usage_stats_handle_t handle; + char * target; + char * taglist; +} ssh_usage_ent_t; + + +globus_result_t +ssh_usage_stats_init(int disable_usage_stats, char *usage_stats_targets) +{ + globus_result_t result; + char * target_str = NULL; + char * ptr = ptr; + char * target = NULL; + char * entry = NULL; + globus_list_t * list = NULL; + ssh_usage_ent_t * usage_ent = NULL; + + if (disable_usage_stats) + return GLOBUS_SUCCESS; + + result = globus_module_activate(GLOBUS_USAGE_MODULE); + if (result != GLOBUS_SUCCESS) + { + error("ERROR: couldn't activate USAGE module"); + return result; + } + + if (!usage_stats_targets || + !strcasecmp(usage_stats_targets, "default")) + target_str = strdup(CILOGON_COLLECTOR); + else + target_str = strdup(usage_stats_targets); + + if (target_str == NULL) + { + error("ERROR: strdup failure for target_str"); + goto error; + } + debug("Processing usage_stats_target (%s)\n", target_str); + + if(target_str && strchr(target_str, '!')) + { + target = target_str; + + do { + usage_ent = (ssh_usage_ent_t *) malloc(sizeof(ssh_usage_ent_t)); + if (usage_ent == NULL) + { + error("ERROR: couldn't allocate for ssh_usage_ent_t"); + goto error; + } + + if ((ptr = strchr(target, ',')) != NULL) + *ptr = '\0'; + + entry = strdup(target); + if (entry == NULL) + { + error("ERROR: strdup failure for target"); + goto error; + } + + if (ptr) + target = ptr + 1; + else + target = NULL; + + if((ptr = strchr(entry, '!')) != NULL) + { + *ptr = '\0'; + usage_ent->taglist = strdup(ptr + 1); + if (usage_ent->taglist == NULL) + { + error("ERROR: strdup failure for taglist"); + goto error; + } + if(strlen(usage_ent->taglist) > SSH_GLOBUS_TAGCOUNT) + { + usage_ent->taglist[SSH_GLOBUS_TAGCOUNT + 1] = '\0'; + } + } + else + { + usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST); + if (usage_ent->taglist == NULL) + { + error("ERROR: couldn't allocate for taglist"); + goto error; + } + } + + if(strcasecmp(usage_ent->taglist, "default") == 0) + { + free(usage_ent->taglist); + usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST); + if (usage_ent->taglist == NULL) + { + error("ERROR: couldn't allocate for taglist"); + goto error; + } + } + else if(strcasecmp(usage_ent->taglist, "all") == 0) + { + free(usage_ent->taglist); + usage_ent->taglist = strdup(SSH_GLOBUS_ALL_TAGLIST); + if (usage_ent->taglist == NULL) + { + error("ERROR: couldn't allocate for taglist"); + goto error; + } + } + + usage_ent->target = entry; + + globus_list_insert(&usage_handle_list, usage_ent); + } + while(target != NULL); + + free(target_str); + } + else + { + usage_ent = (ssh_usage_ent_t *) malloc(sizeof(ssh_usage_ent_t)); + if (usage_ent == NULL) + { + error("ERROR: couldn't allocate for usage_ent"); + goto error; + } + + usage_ent->target = target_str; + usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST); + if (usage_ent->taglist == NULL) + { + error("ERROR: couldn't allocate for taglist"); + goto error; + } + + globus_list_insert(&usage_handle_list, usage_ent); + } + + + for(list = usage_handle_list; + !globus_list_empty(list); + list = globus_list_rest(list)) + { + usage_ent = (ssh_usage_ent_t *) globus_list_first(list); + + usage_ent->handle = NULL; + debug("USAGE: Initializing (%s) (%s)", usage_ent->target?:"NULL", + usage_ent->taglist?:"NULL"); + result = globus_usage_stats_handle_init( + &usage_ent->handle, + SSH_GLOBUS_USAGE_ID, + SSH_GLOBUS_USAGE_VER, + usage_ent->target); + } + + return result; + +error: + if (target_str) + { + free(target_str); + target_str = NULL; + } + if (entry) + { + free(target_str); + target_str = NULL; + } + return GLOBUS_FAILURE; +} + +void +ssh_usage_stats_close(int disable_usage_stats) +{ + globus_list_t *list; + + if (disable_usage_stats) + return; + + list = usage_handle_list; + + while(!globus_list_empty(list)) + { + ssh_usage_ent_t *usage_ent; + + usage_ent = (ssh_usage_ent_t *) + globus_list_remove(&list, list); + + if(usage_ent) + { + if(usage_ent->handle) + { + globus_usage_stats_handle_destroy(usage_ent->handle); + } + if(usage_ent->target) + { + free(usage_ent->target); + } + if(usage_ent->taglist) + { + free(usage_ent->taglist); + } + free(usage_ent); + } + } + usage_handle_list = NULL; +} + +static void +log_usage_stats(char *ssh_release, const char *ssl_release, + char *method, char *mechanism, const char *clientip, + char *username, char *userdn) +{ + globus_result_t result; + globus_list_t * list; + ssh_usage_ent_t * usage_ent; + char * keys[SSH_GLOBUS_TAGCOUNT]; + char * values[SSH_GLOBUS_TAGCOUNT]; + char * ptr; + char * key; + char * value; + int i = 0; + char * save_taglist = NULL; + + for(list = usage_handle_list; + !globus_list_empty(list); + list = globus_list_rest(list)) + { + usage_ent = (ssh_usage_ent_t *) globus_list_first(list); + + if(!usage_ent || usage_ent->handle == NULL) + return; + + if(save_taglist == NULL || + strcmp(save_taglist, usage_ent->taglist) != 0) + { + save_taglist = usage_ent->taglist; + + ptr = usage_ent->taglist; + i = 0; + while(ptr && *ptr) + { + switch(*ptr) + { + case SSH_GLOBUS_USAGE_SSH_VER: + key = "SSH_VER"; + value = ssh_release; + break; + + case SSH_GLOBUS_USAGE_SSL_VER: + key = "SSL_VER"; + value = (char *) ssl_release; + break; + + case SSH_GLOBUS_USAGE_METHOD: + key = "METHOD"; + value = method; + break; + + case SSH_GLOBUS_USAGE_MECHANISM: + key = "MECH"; + value = mechanism?:""; + break; + + case SSH_GLOBUS_USAGE_CLIENTIP: + key = "CLIENTIP"; + value = (char *) clientip?:""; + break; + + case SSH_GLOBUS_USAGE_USERNAME: + key = "USER"; + value = username?:""; + break; + + case SSH_GLOBUS_USAGE_USERDN: + key = "USERDN"; + value = userdn?:""; + break; + + default: + key = NULL; + value = NULL; + break; + } + + if(key != NULL && value != NULL) + { + keys[i] = key; + values[i] = value; + i++; + } + + ptr++; + } + } + +#ifdef HAVE_GLOBUS_USAGE_SEND_ARRAY + result = globus_usage_stats_send_array( + usage_ent->handle, i, keys, values); +#else + if (i) + result = globus_usage_stats_send( + usage_ent->handle, i, + i>0?keys[0]:NULL, i>0?values[0]:NULL, + i>1?keys[1]:NULL, i>1?values[1]:NULL, + i>2?keys[2]:NULL, i>2?values[2]:NULL, + i>3?keys[3]:NULL, i>3?values[3]:NULL, + i>4?keys[4]:NULL, i>4?values[4]:NULL, + i>5?keys[5]:NULL, i>5?values[5]:NULL, + i>6?keys[6]:NULL, i>6?values[6]:NULL); +#endif /* HAVE_GLOBUS_USAGE_SEND_ARRAY */ + } + + return; +} +#endif /* HAVE_GLOBUS_USAGE */ + +void +ssh_globus_send_usage_metrics(char *ssh_release, const char *ssl_release, + char *method, char *mechanism, const char *client_ip, + char *username, char *userdn) +{ +#ifdef HAVE_GLOBUS_USAGE + + log_usage_stats(ssh_release, ssl_release, method, mechanism, + client_ip, username, userdn); + +#endif /* HAVE_GLOBUS_USAGE */ +}