]> andersk Git - moira.git/blob - util/gdss/lib/gdss.c
initial import of gdss from the Athena source tree
[moira.git] / util / gdss / lib / gdss.c
1 /*
2  * $Source$
3  * $Author$
4  * $Header$
5  */
6 /*
7  * GDSS The Generic Digital Signature Service
8  *
9  * gdss.c: Main interface routines
10  */
11
12 #include <BigNum.h>
13 #include <BigRSA.h>
14 #include <krb.h>
15 #include <gdss.h>
16 #include <stdio.h>
17
18 static RSAKeyStorage gdss_pubkey;
19 static int gdss_have_key;
20 static int pfetchkey();
21
22 #ifdef notdef
23 /* This function is obsolete */
24 int GDSS_Sig_Info(Signature, aSigInfo)
25 unsigned char *Signature;
26 SigInfo *aSigInfo;
27 {
28   int status;
29   static int pfetchkey();
30   unsigned char hash[16];
31   unsigned char *cp;
32
33   cp = aSigInfo->rawsig;
34   memset(aSigInfo, 0, sizeof(SigInfo));
35   aSigInfo->rawsig = cp;
36   aSigInfo->SigInfoVersion = 0;
37   do {
38     status = pfetchkey();
39     if (status) break;
40     status = gdss_rverify(Signature, hash, &(*aSigInfo).pname,
41                           &(*aSigInfo).pinst, &(*aSigInfo).prealm,
42                           &gdss_pubkey, &(*aSigInfo).timestamp,
43                           aSigInfo->rawsig);
44   } while(0);
45   return (status);
46 }
47 #endif
48
49 int GDSS_Verify(Data, DataLen, Signature, aSigInfo)
50 unsigned char *Data;
51 unsigned int DataLen;
52 unsigned char *Signature;
53 SigInfo *aSigInfo;
54 {
55   unsigned char hash[16];
56   SigInfo bSigInfo, *iSigInfo;
57   int status;
58   unsigned char *cp;
59
60   if (aSigInfo == NULL) {
61     iSigInfo = &bSigInfo;
62   } else {
63     iSigInfo = aSigInfo;
64   }
65   status = pfetchkey();
66   if (status) return (status);
67
68   memset(&bSigInfo, 0, sizeof(bSigInfo));
69   cp = iSigInfo->rawsig;
70   memset(iSigInfo, 0, sizeof(bSigInfo));
71   iSigInfo->rawsig = cp;
72
73   RSA_MD2(Data, DataLen, hash);
74
75   status = gdss_rverify(Signature, hash, iSigInfo->pname,
76                         iSigInfo->pinst, iSigInfo->prealm,
77                         &gdss_pubkey, &iSigInfo->timestamp, iSigInfo->rawsig);
78
79   if (status) return (status);
80   return (GDSS_SUCCESS);
81 }
82
83 int GDSS_Sig_Size()
84 {
85   int status;
86   int retval;
87   status = pfetchkey();
88   if (status) retval = 512;     /* No provision for errors, so default value */
89   retval = sizeof(SigInfo) + (gdss_pubkey.nl)*4 + GDSS_PAD + 5;
90   return (retval);
91 }
92
93 static int pfetchkey()
94 {
95   FILE *keyf;
96   unsigned char buffer[512];
97
98   if (gdss_have_key) return (0);
99   keyf = fopen("/etc/athena/gdss_public_key", "r");
100   if (keyf == NULL) {
101       keyf = fopen("/afs/net.mit.edu/system/config/gdss_public_key", "r");
102       if (keyf == NULL) return (GDSS_E_NOPUBKEY);
103   }
104   fread(buffer, 1, 512, keyf);
105   fclose(keyf);
106   DecodePublic(buffer, &gdss_pubkey);
107   gdss_have_key++;
108   return (GDSS_SUCCESS);
109 }
110
111 GDSS_Recompose(aSigInfo, signature)
112 SigInfo *aSigInfo;
113 unsigned char *signature;
114 {
115   if (aSigInfo->rawsig == NULL) return (GDSS_E_BADINPUT);
116   return(gdss_recompose(aSigInfo, signature));
117 }
118
119
120 #include <sys/types.h>
121 #include <sys/socket.h>
122 #include <netinet/in.h>
123 #include <netdb.h>
124 #include <sys/time.h>
125 #include <hesiod.h>
126
127 static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
128 GDSS_Sign(Data, DataLen, Signature)
129 unsigned char *Data;
130 unsigned int DataLen;
131 unsigned char *Signature;
132 {
133   KTEXT_ST authent;
134   char lrealm[REALM_SZ];
135   char linst[INST_SZ];
136   char sinst[INST_SZ];
137   char *cp;
138   unsigned char hash[16];
139   unsigned char dhash[16];      /* Second level hash */
140   int s;                        /* Socket to do i/o on */
141   int status;
142   register int i;
143   unsigned int cksum;
144   unsigned char packet[2048];
145   int plen;
146   unsigned char ipacket[2048];
147   int iplen;
148   struct hostent *hp;
149   struct sockaddr_in sin, lsin;
150   fd_set readfds;
151   char **hostname;
152   int trys;
153   char *krb_get_phost();
154
155   memset(packet, 0, sizeof(packet)); /* Zeroize Memory */
156   memset(ipacket, 0, sizeof(ipacket));
157   krb_get_lrealm(lrealm, 1);    /* Get our Kerberos realm */
158
159   RSA_MD2(Data, DataLen, hash);
160   RSA_MD2(hash, 16, dhash);     /* For use of Kerberos */
161   memcpy(packet, hash, 16);
162
163   cksum = 0;
164   for (i = 0; i < 4; i++)       /* High order 32 bits of dhash is the
165                                    Kerberos checksum, I wish we could do
166                                    better, but this is all kerberos allows
167                                    us */
168     cksum = (cksum << 8) + dhash[i];
169
170   /* Use Hesiod to find service location of GDSS Server Here */
171
172   hostname = hes_resolve("gdss", "sloc");
173   if (hostname == NULL) return(-1); /* No hesiod available */
174
175   cp = krb_get_phost(*hostname);
176   if (cp == NULL) return (-1);  /* Should use a better error code */
177
178   strcpy(sinst, cp);
179
180   hp = gethostbyname(*hostname);
181
182   if(hp == NULL) return (-1);   /* Could not find host, you lose */
183
184   memset(&sin, 0, sizeof(sin));
185   sin.sin_family = hp->h_addrtype;
186   memcpy(&sin.sin_addr, hp->h_addr, sizeof(hp->h_addr));
187   sin.sin_port = htons(7201);   /* Should get this from services or Hesiod */
188
189   strcpy(linst, "gdss");        /* Grrr... krb_mk_req bashes its input
190                                    So we better copy it first! */
191   status = krb_mk_req(&authent, linst, sinst, lrealm, cksum);
192   if (status != KSUCCESS) return (GDSS_E_KRBFAIL);
193   packet[0] = 0;                /* Version 0 of protocol */
194   memcpy(&packet[1], hash, 16);
195   memcpy(&packet[17], &authent, sizeof(authent));
196   plen = sizeof(authent) + 16 + 1;      /* KTEXT_ST plus the hash + version */
197
198   s = -1;                       /* "NULL" Value for socket */
199   do {
200     s = socket(AF_INET, SOCK_DGRAM, 0);
201     if (s < 0) {
202       status = GDSS_E_NOSOCKET;
203       break;
204     }
205     if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
206       status = GDSS_E_NOCONNECT;
207       break;
208     }
209     trys = 3;
210     status = GDSS_E_TIMEDOUT;
211     while (trys > 0) {
212       if(send(s, packet, plen, 0) < 0) break;
213       FD_ZERO(&readfds);
214       FD_SET(s, &readfds);
215       if ((select(s+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1)
216           || !FD_ISSET(s, &readfds)) {
217         trys--;
218         continue;
219       }
220       if((iplen = recv(s, (char *)ipacket, 2048, 0)) < 0) break;
221       status = GDSS_SUCCESS;
222       break;
223     }
224   } while (0);
225   shutdown(s, 0);
226   close(s);
227   if (status != GDSS_SUCCESS) return (status);
228   memcpy(Signature, ipacket, iplen);
229   return (GDSS_SUCCESS);
230 }
This page took 0.052829 seconds and 5 git commands to generate.