2 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 /* KClient.c - KClient glue to krb4.dll
35 * Author: Jörgen Karlsson - d93-jka@nada.kth.se
41 RCSID("$Id: KClient.c,v 1.14 1999/12/02 16:58:40 joda Exp $");
44 #ifdef WIN32 /* Visual C++ 4.0 (Windows95/NT) */
50 #include "passwd_dlg.h"
59 HWND wnd = GetActiveWindow();
60 MessageBox(wnd, text, "KClient message", MB_OK|MB_APPLMODAL);
64 SendTicketForService(LPSTR service, LPSTR version, int fd)
69 des_key_schedule schedule;
70 char name[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
72 static KClientSessionInfo foo;
75 kname_parse(name, inst, realm, service);
76 strlcpy(foo.realm, realm, sizeof(foo.realm));
78 if(KClientStatus(&foo) == KClientNotLoggedIn)
79 KClientLogin(&foo, &key);
81 ret = krb_sendauth (0, fd, &ticket,
82 name, inst, realm, 17, &mdat,
83 &cred, &schedule, NULL, NULL, version);
90 DllMain(HANDLE hInst, ULONG reason, LPVOID lpReserved)
92 WORD wVersionRequested;
97 case DLL_PROCESS_ATTACH:
98 wVersionRequested = MAKEWORD(1, 1);
100 err = WSAStartup(wVersionRequested, &wsaData);
104 /* Tell the user that we couldn't find a useable */
106 msg("Cannot find winsock.dll");
110 case DLL_PROCESS_DETACH:
118 KClientMessage(char *text, Kerr error)
124 /* KClientInitSession
125 * You need to call this routine before calling most other routines.
126 * It initializes a KClientSessionInfo structure.
127 * The local and remote addresses are for use in KClientEncrypt,
128 * KClientDecrypt, KClientMakeSendAuth and KClientVerifySendAuth.
129 * If you don't use any of these routines it's perfectly OK to do the following...
130 * err = KClientInitSession(session,0,0,0,0);
133 KClientInitSession(KClientSessionInfo *session,
135 unsigned short lPort,
137 unsigned short fPort)
139 session->lAddr = lAddr;
140 session->lPort = lPort;
141 session->fAddr = fAddr;
142 session->fPort = fPort;
143 if(tf_get_pname(session->user) != KSUCCESS)
144 *(session->user) = '\0';
145 if(tf_get_pinst(session->inst) != KSUCCESS)
146 *(session->inst) = '\0';
147 krb_get_lrealm (session->realm, 1);
149 strlcpy(guser, session->user, sizeof(guser));
157 /* KClientGetTicketForService
158 * This routine gets an authenticator to be passed to a service.
159 * If the user isn't already logged in the user is prompted for a password.
162 KClientGetTicketForService(KClientSessionInfo *session,
165 unsigned long *buflen)
170 char serv[255], inst[255], realm[255];
173 // KClientSetUserName(session->user);
174 err = kname_parse(serv,inst,realm,service);
176 strlcpy(session->realm, realm, sizeof(session->realm));
178 strlcpy(realm, session->realm, sizeof(realm));
179 if(KClientStatus(session) == KClientNotLoggedIn)
180 if((err = KClientLogin(session, &k)) != KSUCCESS)
183 if((err = krb_mk_req(&ticket, serv, inst, realm, 0)) != KSUCCESS)
184 return KClientMessage(KClientErrorText(err,0),err);
185 if((err = krb_get_cred(serv, inst, realm, &c)) != KSUCCESS)
186 return KClientMessage(KClientErrorText(err,0),err);
188 if(*buflen >= ticket.length)
190 *buflen = ticket.length + sizeof(unsigned long);
191 CopyMemory(buf, &ticket, *buflen);
192 CopyMemory(session->key, c.session, sizeof(session->key));
201 * This routine "logs in" by getting a ticket granting ticket from kerberos.
202 * It returns the user's private key which can be used to automate login at
203 * a later time with KClientKeyLogin.
207 KClientLogin(KClientSessionInfo *session,
208 KClientKey *privateKey)
214 if((err = pwd_dialog(guser, passwd)))
216 if(KClientStatus(session) == KClientNotLoggedIn)
219 if((err = krb_get_pw_in_tkt(guser, session->inst, session->realm,
220 "krbtgt", session->realm,
221 DEFAULT_TKT_LIFE, passwd)) != KSUCCESS)
222 return KClientMessage(KClientErrorText(err,0),err);
224 if((err = krb_get_cred("krbtgt", session->realm,
225 session->realm, &c)) == KSUCCESS)
226 CopyMemory(privateKey, c.session, sizeof(*privateKey));
231 /* KClientPasswordLogin
232 * This routine is similiar to KClientLogin but instead of prompting the user
233 * for a password it uses the password supplied to establish login.
236 KClientPasswordLogin(KClientSessionInfo *session,
238 KClientKey *privateKey)
240 return krb_get_pw_in_tkt(guser, session->inst, session->realm,
255 * This routine is similiar to KClientLogin but instead of prompting the user
256 * for a password it uses the private key supplied to establish login.
259 KClientKeyLogin(KClientSessionInfo *session,
260 KClientKey *privateKey)
262 return krb_get_in_tkt(guser, session->inst, session->realm,
272 * This routine destroys all credentials stored in the credential cache
273 * effectively logging the user out.
283 * This routine returns the user's login status which can be
284 * KClientLoggedIn or KClientNotLoggedIn.
287 KClientStatus(KClientSessionInfo *session)
290 if(krb_get_cred("krbtgt",
292 session->realm, &c) == KSUCCESS)
293 return KClientLoggedIn;
295 return KClientNotLoggedIn;
299 /* KClientGetUserName
300 * This routine returns the name the user supplied in the login dialog.
301 * No name is returned if the user is not logged in.
304 KClientGetUserName(char *user)
311 /* KClientSetUserName
312 * This routine sets the name that will come up in the login dialog
313 * the next time the user is prompted for a password.
316 KClientSetUserName(char *user)
318 strlcpy(guser, user, sizeof(guser));
323 /* KClientCacheInitialTicket
324 * This routine is used to obtain a ticket for the password changing service.
327 KClientCacheInitialTicket(KClientSessionInfo *session,
334 /* KClientGetSessionKey
335 * This routine can be used to obtain the session key which is stored
336 * in the KClientSessionInfo record. The session key has no usefullness
337 * with any KClient calls but it can be used to with the MIT kerberos API.
340 KClientGetSessionKey(KClientSessionInfo *session,
341 KClientKey *sessionKey)
343 CopyMemory(sessionKey, session->key, sizeof(*sessionKey));
348 /* KClientMakeSendAuth
349 * This routine is used to create an authenticator that is the same as those
350 * created by the kerberos routine SendAuth.
353 KClientMakeSendAuth(KClientSessionInfo *session,
356 unsigned long *buflen,
358 char *applicationVersion)
364 /* KClientVerifySendAuth
365 * This routine is used to verify a response made by a server doing RecvAuth.
366 * The two routines KClientMakeSendAuth and KClientVerifySendAuth together
367 * provide the functionality of SendAuth minus the transmission of authenticators
368 * between client->server->client.
371 KClientVerifySendAuth(KClientSessionInfo *session,
373 unsigned long *buflen)
380 * This routine encrypts a series a bytes for transmission to the remote host.
381 * For this to work properly you must be logged in and you must have specified
382 * the remote and local addresses in KClientInitSession. The unencrypted
383 * message pointed to by buf and of length buflen is returned encrypted
384 * in encryptBuf of length encryptLength.
385 * The encrypted buffer must be at least 26 bytes longer the buf.
388 KClientEncrypt(KClientSessionInfo *session,
390 unsigned long buflen,
392 unsigned long *encryptLength)
395 des_cfb64_encrypt(buf, encryptBuf, buflen,
396 (struct des_ks_struct*) session->key,
403 * This routine decrypts a series of bytes received from the remote host.
405 * NOTE: this routine will not reverse a KClientEncrypt call.
406 * It can only decrypt messages sent from the remote host.
408 * Instead of copying the decrypted message to an out buffer,
409 * the message is decrypted in place and you are returned
410 * an offset into the buffer where the decrypted message begins.
413 KClientDecrypt(KClientSessionInfo *session,
415 unsigned long buflen,
416 unsigned long *decryptOffset,
417 unsigned long *decryptLength)
420 des_cfb64_encrypt(buf, buf, buflen,
421 (struct des_ks_struct*)session->key, 0, &num, 0);
423 *decryptLength = buflen;
429 * This routine returns a text description of errors returned by any of
430 * the calls in this library.
433 KClientErrorText(Kerr err,
436 char *t = krb_get_err_text(err);