]> andersk Git - moira.git/blobdiff - server/mr_sauth.c
Command line printer manipulation client, and build goo.
[moira.git] / server / mr_sauth.c
index 2466c6d20ada7bba3d00fe230a93da9ba0dd7917..2cc1a486f81c3baac54a3c624b04ea7b1ac6092b 100644 (file)
-/*
- *     $Source$
- *     $Author$
- *     $Header$
+/* $Id$
  *
- *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ * Handle server side of authentication
  *
- *     $Log$
- *     Revision 1.5  1987-07-14 00:40:18  wesommer
- *     Rearranged logging.
+ * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
  *
- * Revision 1.4  87/06/30  20:03:46  wesommer
- * Put parsed kerberos principal name into the per-client structure.
- * 
- * Revision 1.3  87/06/21  16:40:10  wesommer
- * Performance work, rearrangement of include files.
- * 
- * Revision 1.2  87/06/04  01:34:35  wesommer
- * Added logging of arguments for some perverse reason.
- * 
- * Revision 1.1  87/06/02  20:06:57  wesommer
- * Initial revision
- * 
  */
 
-#ifndef lint
-static char *rcsid_sms_sauth_c = "$Header$";
-#endif lint
+#include <mit-copyright.h>
+#include "mr_server.h"
+
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+RCSID("$Header$");
+
+extern char *whoami, *host;
+extern int proxy_acl;
+extern krb5_context context;
 
-extern int krb_err_base;
-#include <strings.h>
-#include "sms_server.h"
+static int set_client(client *cl, char *kname,
+                     char *name, char *inst, char *realm);
 
-extern char buf1[];
-extern char *whoami;
-extern char *malloc();
+#ifdef HAVE_KRB4
+typedef struct _replay_cache {
+  KTEXT_ST auth;
+  time_t expires;
+  struct _replay_cache *next;
+} replay_cache;
+
+replay_cache *rcache = NULL;
+#endif
 
 /*
- * Handle a SMS_AUTH RPC request.
+ * Handle a MOIRA_AUTH RPC request.
  *
  * argv[0] is a kerberos authenticator.  Decompose it, and if
- * successful, store the name the user authenticated to in 
+ * successful, store the name the user authenticated to in
  * cl->cl_name.
  */
 
-void
-do_auth(cl)
-       client *cl;
+void do_auth(client *cl)
 {
-       KTEXT_ST auth;
-       AUTH_DAT ad;
-       int status;
-       char buf[REALM_SZ+INST_SZ+ANAME_SZ];
-       extern int krb_err_base;
-       
-       auth.length = cl->args->sms_argl[0];
-
-       bcopy(cl->args->sms_argv[0], (char *)auth.dat, auth.length);
-       auth.mbz = 0;
-       
-       if ((status = rd_ap_req (&auth, "sms", "sms", cl->haddr.sin_addr,
-                                &ad, "")) != KSUCCESS) {
-               status += krb_err_base;
-               cl->reply.sms_status = status;
-               if (log_flags & LOG_RES)
-                       com_err(whoami, status, "(authentication failed)");
-               return;
-       }
-       bcopy(ad.pname, cl->kname.name, ANAME_SZ);
-       bcopy(ad.pinst, cl->kname.inst, INST_SZ);
-       bcopy(ad.prealm, cl->kname.realm, REALM_SZ);
-       
-       (void) strcpy(buf, ad.pname);
-       if(ad.pinst[0]) {
-               (void) strcat(buf, ".");
-               (void) strcat(buf, ad.pinst);
+#ifdef HAVE_KRB4
+  KTEXT_ST auth;
+  AUTH_DAT ad;
+  int status;
+  replay_cache *rc, *rcnew;
+  time_t now;
+
+  auth.length = cl->req.mr_argl[0];
+  memcpy(auth.dat, cl->req.mr_argv[0], auth.length);
+  auth.mbz = 0;
+
+  if ((status = krb_rd_req(&auth, MOIRA_SNAME, host,
+                          cl->haddr.sin_addr.s_addr, &ad, "")))
+    {
+      status += ERROR_TABLE_BASE_krb;
+      client_reply(cl, status);
+      com_err(whoami, status, " (authentication failed)");
+      return;
+    }
+
+  if (!rcache)
+    {
+      rcache = xmalloc(sizeof(replay_cache));
+      memset(rcache, 0, sizeof(replay_cache));
+    }
+
+  /* scan replay cache */
+  for (rc = rcache->next; rc; rc = rc->next)
+    {
+      if (auth.length == rc->auth.length &&
+         !memcmp(&(auth.dat), &(rc->auth.dat), auth.length))
+       {
+         com_err(whoami, 0,
+                 "Authenticator replay from %s using authenticator for %s",
+                 inet_ntoa(cl->haddr.sin_addr),
+                 mr_kname_unparse(ad.pname, ad.pinst, ad.prealm));
+         com_err(whoami, KE_RD_AP_REPEAT, " (authentication failed)");
+         client_reply(cl, KE_RD_AP_REPEAT);
+         return;
        }
-       (void) strcat(buf, "@");
-       (void) strcat(buf, ad.prealm);
-       if (cl->clname) free((char *)cl->clname);
-       
-       cl->clname = (char *)malloc((unsigned)(strlen(buf)+1));
-       (void) strcpy(cl->clname, buf);
-       if (log_flags & LOG_RES) {
-               (void) sprintf(buf1, "Authenticated to %s", cl->clname);
-               com_err(whoami, 0, buf1);
+    }
+
+  /* add new entry */
+  time(&now);
+  rcnew = xmalloc(sizeof(replay_cache));
+  memcpy(&(rcnew->auth), &auth, sizeof(KTEXT_ST));
+  rcnew->expires = now + 2 * CLOCK_SKEW;
+  rcnew->next = rcache->next;
+  rcache->next = rcnew;
+
+  /* clean cache */
+  for (rc = rcnew; rc->next; )
+    {
+      if (rc->next->expires < now)
+       {
+         rcnew = rc->next;
+         rc->next = rc->next->next;
+         free(rcnew);
        }
+      else
+       rc = rc->next;
+    }
+
+  status = set_client(cl, mr_kname_unparse(ad.pname, ad.pinst, ad.prealm),
+                     ad.pname, ad.pinst, ad.prealm);
+
+  strncpy(cl->entity, cl->req.mr_argv[1], sizeof(cl->entity) - 1);
+  cl->entity[sizeof(cl->entity) - 1] = 0;
+
+  memset(&ad, 0, sizeof(ad));  /* Clean up session key, etc. */
+
+  com_err(whoami, 0, "Auth to %s using %s, uid %d cid %d",
+         cl->clname, cl->entity, cl->users_id, cl->client_id);
+
+  if (status != MR_SUCCESS || cl->users_id != 0)
+    client_reply(cl, status);
+  else
+    client_reply(cl, MR_USER_AUTH);
+#else
+  client_reply(cl, MR_NO_KRB4);
+#endif
+}
+
+void do_proxy(client *cl)
+{
+  char name[ANAME_SZ] = "\0", inst[INST_SZ] = "\0", realm[REALM_SZ] = "\0";
+  char kname[MAX_K_NAME_SZ];
+
+  if (cl->proxy_id)
+    {
+      com_err(whoami, MR_PERM, "Cannot re-proxy");
+      client_reply(cl, MR_PERM);
+      return;
+    }
+
+  if (mr_kname_parse(name, inst, realm, cl->req.mr_argv[0]) != 0)
+    {
+      com_err(whoami, KE_KNAME_FMT, "while parsing proxy name %s",
+             cl->req.mr_argv);
+      client_reply(cl, KE_KNAME_FMT);
+      return;
+    }
+
+  if (!*realm)
+    {
+      strcpy(realm, krb_realm);
+      sprintf(kname, "%s@%s", cl->req.mr_argv[0], realm);
+    }
+  else
+    strcpy(kname, cl->req.mr_argv[0]);
+    
+  if (find_member("LIST", proxy_acl, cl))
+    {
+      cl->proxy_id = cl->client_id;
+      set_client(cl, kname, name, inst, realm);
+      com_err(whoami, 0, "Proxy authentication as %s (uid %d cid %d) via %s",
+             kname, cl->users_id, cl->client_id, cl->req.mr_argv[1]);
+      client_reply(cl, MR_SUCCESS);
+    }
+  else
+    {
+      com_err(whoami, MR_PERM, "Proxy authentication denied");
+      client_reply(cl, MR_PERM);
+    }
+}
+
+static int set_client(client *cl, char *kname,
+                     char *name, char *inst, char *realm)
+{
+  int ok;
+
+  strncpy(cl->clname, kname, sizeof(cl->clname));
+  cl->clname[sizeof(cl->clname) - 1] = '\0';
+
+  if ((!inst || inst[0] == 0) && !strcmp(realm, krb_realm))
+    ok = 1;
+  else
+    ok = 0;
+  /* this is in a separate function because it accesses the database */
+  return set_krb_mapping(cl->clname, name, ok, &cl->client_id, &cl->users_id);
+}
+
+void do_krb5_auth(client *cl)
+{
+  krb5_data auth;
+  krb5_auth_context auth_con = NULL;
+  krb5_principal server = NULL, client = NULL;
+  krb5_ticket *ticket;
+  char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+  int status;
+
+  ticket = NULL;
+
+  status = krb5_auth_con_init(context, &auth_con);
+  if (status)
+    {
+      client_reply(cl, status);
+      com_err(whoami, status, "(krb5 auth context init failed)");
+      goto out;
+    }
+
+  status = krb5_sname_to_principal(context, host, MOIRA_SNAME, 
+                                   KRB5_NT_SRV_HST, &server);
+  if (status)
+    {
+      client_reply(cl, status);
+      com_err(whoami, status, "(krb5_sname_to_principal failed)");
+      goto out;
+    }
+
+  auth.length = cl->req.mr_argl[0];
+  auth.data = cl->req.mr_argv[0];
+
+  status = krb5_rd_req(context, &auth_con, &auth, server, NULL, NULL,
+                       &ticket);
+  if (status)
+    {
+      client_reply(cl, status);
+      com_err(whoami, status, " (krb5 authentication failed)");
+      goto out;
+    }
+
+  status = krb5_copy_principal(context, ticket->enc_part2->client, &client);
+  if (status)
+    {
+      client_reply(cl, status);
+      com_err(whoami, status, " (krb5_copy_principal failed)");
+      goto out;
+    }
+
+  /* Always convert to krb4 style principal name for now. */
+  status = krb5_524_conv_principal(context, client, name, inst, realm);
+  if (status)
+    {
+      client_reply(cl, status);
+      com_err(whoami, status, " (krb5_524_conv_principal failed)");
+      goto out;
+    }
+  status = set_client(cl, mr_kname_unparse(name, inst, realm), name, inst,
+                     realm);
+
+  strncpy(cl->entity, cl->req.mr_argv[1], sizeof(cl->entity) - 1);
+  cl->entity[sizeof(cl->entity) - 1] = 0;
+
+  com_err(whoami, 0, "krb5 auth to %s using %s, uid %d cid %d",
+         cl->clname, cl->entity, cl->users_id, cl->client_id);
+
+  if (status != MR_SUCCESS || cl->users_id != 0)
+    client_reply(cl, status);
+  else
+    client_reply(cl, MR_USER_AUTH);
+
+ out:
+  if (client)
+    krb5_free_principal(context, client);
+  if (server)
+    krb5_free_principal(context, server);
+  if (ticket)
+    krb5_free_ticket(context, ticket);
+  if (auth_con)
+    krb5_auth_con_free(context, auth_con);
+  return;
 }
This page took 0.065201 seconds and 4 git commands to generate.