]> andersk Git - moira.git/blobdiff - server/mr_sauth.c
Command line printer manipulation client, and build goo.
[moira.git] / server / mr_sauth.c
index 2cca856708271c21314f3745ba3b67a8ccc3fe1e..2cc1a486f81c3baac54a3c624b04ea7b1ac6092b 100644 (file)
 RCSID("$Header$");
 
 extern char *whoami, *host;
+extern int proxy_acl;
+extern krb5_context context;
 
+static int set_client(client *cl, char *kname,
+                     char *name, char *inst, char *realm);
+
+#ifdef HAVE_KRB4
 typedef struct _replay_cache {
   KTEXT_ST auth;
   time_t expires;
@@ -30,6 +36,7 @@ typedef struct _replay_cache {
 } replay_cache;
 
 replay_cache *rcache = NULL;
+#endif
 
 /*
  * Handle a MOIRA_AUTH RPC request.
@@ -39,16 +46,17 @@ replay_cache *rcache = NULL;
  * cl->cl_name.
  */
 
-void do_auth(client *cl, mr_params req)
+void do_auth(client *cl)
 {
+#ifdef HAVE_KRB4
   KTEXT_ST auth;
   AUTH_DAT ad;
-  int status, ok;
+  int status;
   replay_cache *rc, *rcnew;
   time_t now;
 
-  auth.length = req.mr_argl[0];
-  memcpy(auth.dat, req.mr_argv[0], auth.length);
+  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,
@@ -75,7 +83,7 @@ void do_auth(client *cl, mr_params req)
          com_err(whoami, 0,
                  "Authenticator replay from %s using authenticator for %s",
                  inet_ntoa(cl->haddr.sin_addr),
-                 kname_unparse(ad.pname, ad.pinst, ad.prealm));
+                 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;
@@ -103,31 +111,163 @@ void do_auth(client *cl, mr_params req)
        rc = rc->next;
     }
 
-  memcpy(cl->kname.name, ad.pname, ANAME_SZ);
-  memcpy(cl->kname.inst, ad.pinst, INST_SZ);
-  memcpy(cl->kname.realm, ad.prealm, REALM_SZ);
-  strncpy(cl->clname, kname_unparse(ad.pname, ad.pinst, ad.prealm),
-         sizeof(cl->clname));
+  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 (ad.pinst[0] == 0 && !strcmp(ad.prealm, krb_realm))
+  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 */
-  status = set_krb_mapping(cl->clname, ad.pname, ok,
-                          &cl->client_id, &cl->users_id);
+  return set_krb_mapping(cl->clname, name, ok, &cl->client_id, &cl->users_id);
+}
 
-  strncpy(cl->entity, req.mr_argv[1], 8);
-  cl->entity[8] = 0;
+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;
 
-  memset(&ad, 0, sizeof(ad));  /* Clean up session key, etc. */
+  ticket = NULL;
 
-  com_err(whoami, 0, "Auth to %s using %s, uid %d cid %d",
+  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.040901 seconds and 4 git commands to generate.