]> andersk Git - moira.git/blobdiff - clients/userreg/reg_stubs.c
new operations for secure passwords
[moira.git] / clients / userreg / reg_stubs.c
index 9838621d95de2d8d22228fb5a398f608b55cb876..b5194f356f6b3e0220aff44ceefc9b628dbec9dd 100644 (file)
@@ -20,15 +20,19 @@ static char *rcsid_reg_stubs_c = "$Header$";
 #include <netinet/in.h>
 #include <netdb.h>
 #include <des.h>
+#include <krb.h>
+#include <krb_err.h>
 #include <errno.h>
 #include <moira.h>
 #include <moira_site.h>
 #include "ureg_err.h"
 #include "ureg_proto.h"
 #include <strings.h>
+#include <ctype.h>
 
 static int reg_sock = -1;
 static int seq_no = 0;
+static char *host;
 extern errno;
 #define UNKNOWN_HOST -1
 #define UNKNOWN_SERVICE -2
@@ -42,7 +46,7 @@ extern errno;
 ureg_init()
 {
     struct servent *sp;
-    char *host, **p, *s;
+    char **p, *s;
     struct hostent *hp;
     struct sockaddr_in sin;
     extern char *getenv(), **hes_resolve();
@@ -216,6 +220,127 @@ get_krb(first, last, idnumber, hashidnumber, password)
                        UREG_GET_KRB));
 }
 
+
+/* The handles the operations for secure passwords.
+ * To find out if a user has a secure instance, only the login name
+ * and the opcode = UREG_GET_SECURE need to be specified (but the
+ * other strings must be valid char*'s).  This will return
+ * UREG_ALREADY_REGISTERED if it is set, or SUCCESS if not.
+ * To set the password, fill in the rest of the fields, and
+ * use opcode = UREG_SET_SECURE.  This returns SUCCESS or any number
+ * of failure codes.
+ */
+
+do_secure_operation(login, idnumber, passwd, newpasswd, opcode)
+    char *login, *idnumber, *passwd, *newpasswd;
+    u_long opcode;
+{
+    char buf[1500], data[128], tktstring[128];
+    int version = ntohl((u_long)1);
+    int call = ntohl(opcode);
+    char inst[INST_SZ], hosti[INST_SZ];
+    char *bp = buf, *src, *dst, *realm;
+    int len, status, i;
+    KTEXT_ST cred;
+    CREDENTIALS creds;
+    Key_schedule keys;
+    char *krb_get_phost(), *krb_realmofhost();
+    
+    bcopy((char *)&version, bp, sizeof(int));
+    bp += sizeof(int);
+    seq_no++;
+    bcopy((char *)&seq_no, bp, sizeof(int));
+
+    bp += sizeof(int);
+
+    bcopy((char *)&call, bp, sizeof(int));
+
+    bp += sizeof(int);
+
+    /* put the login name in the firstname field */
+    (void) strcpy(bp, login);
+    bp += strlen(bp)+1;
+
+    /* the old lastname field */
+    (void) strcpy(bp, "");
+    bp += strlen(bp)+1;
+
+    /* don't overwrite existing ticket file */
+    (void) sprintf(tktstring, "/tmp/tkt_cpw_%d",getpid());
+    krb_set_tkt_string(tktstring);
+
+    /* get realm and canonizalized hostname of server */
+    realm = krb_realmofhost(host);
+    for (src = host, dst = hosti; *src && *src != '.'; src++)
+      if (isupper(*src))
+       *dst++ = tolower(*src);
+      else
+       *dst++ = *src;
+    *dst = 0;
+    inst[0] = 0;
+    inst[0] = 0;
+
+    /* get changepw tickets.  We use this service because it's the
+     * only one that guarantees we used the password rather than a
+     * ticket granting ticket.
+     */
+    status = krb_get_pw_in_tkt(login, inst, realm,
+                              "changepw", hosti, 5, passwd);
+    bzero(passwd, strlen(passwd));
+    if (status) {
+       bzero(newpasswd, strlen(newpasswd));
+       return (status + krb_err_base);
+    }
+
+    status = krb_mk_req(&cred, "changepw", hosti, realm, 0);
+    if (status) {
+       bzero(newpasswd, strlen(newpasswd));
+       return (status + krb_err_base);
+    }
+
+    /* round up to word boundry */
+    bp = (char *)((((u_long)bp)+3)&0xfffffffc);
+
+    /* put the ticket in the packet */
+    len = cred.length;
+    cred.length = htonl(cred.length);
+    bcopy(&(cred), bp, sizeof(int)+len);
+#ifdef DEBUG
+    com_err("test", 0, "Cred: length %d", len);
+    for (i = 0; i < len; i += 16)
+      com_err("test", 0, " %02x %02x %02x %02x %02x %02x %02x %02x  %02x %02x %02x %02x %02x %02x %02x %02x",
+             cred.dat[i+0], cred.dat[i+1], cred.dat[i+2], cred.dat[i+3],
+             cred.dat[i+4], cred.dat[i+5], cred.dat[i+6], cred.dat[i+7],
+             cred.dat[i+8], cred.dat[i+9], cred.dat[i+10], cred.dat[i+11],
+             cred.dat[i+12], cred.dat[i+13], cred.dat[i+14], cred.dat[i+15]);
+#endif /* DEBUG */
+    bp += sizeof(int) + len;
+
+    /* encrypt the data in the session key */
+    sprintf(data, "%s,%s", idnumber, newpasswd);
+    len = strlen(data);
+    len = ((len + 7) >> 3) << 3;
+
+    status = krb_get_cred("changepw", hosti, realm, &creds);
+    if (status) {
+       bzero(newpasswd, strlen(newpasswd));
+       bzero(data, strlen(data));
+       return (status + krb_err_base);
+    }
+    dest_tkt();
+
+    des_key_sched(creds.session, keys);
+    des_pcbc_encrypt(data, bp + sizeof(int), len, keys, creds.session, 1);
+    *((int *)bp) = htonl(len);
+    bzero(data, strlen(data));
+
+    bp += len + sizeof(int);
+    
+    len = bp - buf;
+    return do_call(buf, len, seq_no, 0);
+
+}
+
 static do_call(buf, len, seq_no, login)
     char *buf;
     char *login;
This page took 0.05805 seconds and 4 git commands to generate.