]> andersk Git - gssapi-openssh.git/blobdiff - openssh/ssh-globus-usage.c
Added support for reporting usage metrics.
[gssapi-openssh.git] / openssh / ssh-globus-usage.c
diff --git a/openssh/ssh-globus-usage.c b/openssh/ssh-globus-usage.c
new file mode 100644 (file)
index 0000000..3e30504
--- /dev/null
@@ -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 <stdarg.h>
+
+#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 */
+}
This page took 0.097816 seconds and 4 git commands to generate.