[24250] | 1 | /* $Id: auth_002.c,v 1.12 2009-12-29 17:29:34 zacheiss Exp $ |
---|
[23095] | 2 | * |
---|
| 3 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. |
---|
| 4 | * For copying and distribution information, please see the file |
---|
| 5 | * <mit-copyright.h>. |
---|
| 6 | */ |
---|
| 7 | |
---|
| 8 | #include <mit-copyright.h> |
---|
| 9 | #include <moira.h> |
---|
| 10 | #include "update_server.h" |
---|
| 11 | |
---|
| 12 | #include <sys/utsname.h> |
---|
| 13 | |
---|
| 14 | #include <errno.h> |
---|
| 15 | #include <stdio.h> |
---|
| 16 | #include <string.h> |
---|
| 17 | |
---|
[23882] | 18 | #ifdef HAVE_KRB4 |
---|
[23095] | 19 | #include <krb.h> |
---|
[23882] | 20 | #endif |
---|
[23095] | 21 | |
---|
[24250] | 22 | RCSID("$Header: /afs/.athena.mit.edu/astaff/project/moiradev/repository/moira/update/auth_002.c,v 1.12 2009-12-29 17:29:34 zacheiss Exp $"); |
---|
[23095] | 23 | |
---|
| 24 | static char service[] = "rcmd"; |
---|
| 25 | static char master[] = "sms"; |
---|
| 26 | static char qmark[] = "???"; |
---|
[23882] | 27 | #ifdef HAVE_KRB4 |
---|
[23095] | 28 | extern des_cblock session; |
---|
[23882] | 29 | #endif |
---|
[23095] | 30 | |
---|
| 31 | /* |
---|
| 32 | * authentication request auth_002: |
---|
| 33 | * |
---|
| 34 | * >>> (STRING) "auth_002" |
---|
| 35 | * <<< (int) 0 |
---|
| 36 | * >>> (STRING) ticket |
---|
| 37 | * <<< (int) code |
---|
| 38 | * <<< (STRING) nonce |
---|
| 39 | * >>> (STRING) encrypted nonce |
---|
| 40 | * <<< (int) code |
---|
| 41 | * |
---|
| 42 | */ |
---|
| 43 | |
---|
| 44 | void auth_002(int conn, char *str) |
---|
| 45 | { |
---|
[23882] | 46 | #ifdef HAVE_KRB4 |
---|
[23095] | 47 | char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ]; |
---|
| 48 | AUTH_DAT ad; |
---|
| 49 | char *p, *first, *data; |
---|
| 50 | size_t size; |
---|
| 51 | KTEXT_ST ticket_st; |
---|
| 52 | des_key_schedule sched; |
---|
| 53 | des_cblock nonce, nonce2; |
---|
| 54 | long code; |
---|
| 55 | |
---|
| 56 | send_ok(conn); |
---|
| 57 | |
---|
| 58 | recv_string(conn, &data, &size); |
---|
| 59 | if (size > sizeof(ticket_st.dat)) |
---|
| 60 | { |
---|
| 61 | code = KE_RD_AP_UNDEC; |
---|
| 62 | com_err(whoami, code, ": authenticator too large"); |
---|
| 63 | send_int(conn, code); |
---|
| 64 | return; |
---|
| 65 | } |
---|
| 66 | memcpy(ticket_st.dat, data, size); |
---|
| 67 | free(data); |
---|
| 68 | ticket_st.mbz = 0; |
---|
| 69 | ticket_st.length = size; |
---|
| 70 | code = krb_rd_req(&ticket_st, service, krb_get_phost(hostname), 0, |
---|
| 71 | &ad, KEYFILE); |
---|
| 72 | if (code) |
---|
| 73 | { |
---|
| 74 | code += ERROR_TABLE_BASE_krb; |
---|
| 75 | strcpy(ad.pname, qmark); |
---|
| 76 | strcpy(ad.pinst, qmark); |
---|
| 77 | strcpy(ad.prealm, qmark); |
---|
| 78 | goto auth_failed; |
---|
| 79 | } |
---|
| 80 | |
---|
| 81 | /* If there is an auth record in the config file matching the |
---|
| 82 | * authenticator we received, then accept it. If there's no |
---|
| 83 | * auth record, assume [master]@[local realm]. |
---|
| 84 | */ |
---|
| 85 | if ((first = p = config_lookup("auth"))) |
---|
| 86 | { |
---|
| 87 | do |
---|
| 88 | { |
---|
| 89 | kname_parse(aname, ainst, arealm, p); |
---|
| 90 | if (strcmp(aname, ad.pname) || |
---|
| 91 | strcmp(ainst, ad.pinst) || |
---|
| 92 | strcmp(arealm, ad.prealm)) |
---|
| 93 | p = config_lookup("auth"); |
---|
| 94 | else |
---|
| 95 | p = first; |
---|
| 96 | } |
---|
| 97 | while (p != first); |
---|
| 98 | } |
---|
| 99 | else |
---|
| 100 | { |
---|
| 101 | strcpy(aname, master); |
---|
| 102 | strcpy(ainst, ""); |
---|
| 103 | if (krb_get_lrealm(arealm, 1)) |
---|
| 104 | strcpy(arealm, KRB_REALM); |
---|
| 105 | } |
---|
| 106 | code = EPERM; |
---|
| 107 | if (strcmp(aname, ad.pname) || |
---|
| 108 | strcmp(ainst, ad.pinst) || |
---|
| 109 | strcmp(arealm, ad.prealm)) |
---|
| 110 | goto auth_failed; |
---|
| 111 | |
---|
| 112 | send_ok(conn); |
---|
| 113 | |
---|
| 114 | /* replay protection */ |
---|
| 115 | des_random_key(&nonce); |
---|
| 116 | send_string(conn, (char *)nonce, sizeof(nonce)); |
---|
| 117 | recv_string(conn, &data, &size); |
---|
| 118 | des_key_sched(ad.session, sched); |
---|
[24250] | 119 | des_ecb_encrypt((des_cblock *)data, &nonce2, sched, 0); |
---|
[23095] | 120 | free(data); |
---|
| 121 | if (memcmp(nonce, nonce2, sizeof(nonce))) |
---|
| 122 | goto auth_failed; |
---|
| 123 | send_ok(conn); |
---|
| 124 | |
---|
| 125 | have_authorization = 1; |
---|
| 126 | /* Stash away session key */ |
---|
| 127 | memcpy(session, ad.session, sizeof(session)); |
---|
| 128 | return; |
---|
| 129 | |
---|
| 130 | auth_failed: |
---|
| 131 | com_err(whoami, code, "auth for %s.%s@%s failed", |
---|
| 132 | ad.pname, ad.pinst, ad.prealm); |
---|
| 133 | send_int(conn, code); |
---|
[23882] | 134 | #else |
---|
[23932] | 135 | send_int(conn, MR_NO_KRB4); |
---|
[23882] | 136 | #endif |
---|
[23095] | 137 | } |
---|