📄 k5auth.c
字号:
/* $XConsortium: k5auth.c,v 1.9 95/04/06 16:10:29 mor Exp $ *//* $XFree86: xc/programs/Xserver/os/k5auth.c,v 3.2 1996/05/10 07:02:15 dawes Exp $ *//*Copyright (c) 1993, 1994 X ConsortiumPermission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice shall be includedin all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESSOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OROTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OROTHER DEALINGS IN THE SOFTWARE.Except as contained in this notice, the name of the X Consortium shallnot be used in advertising or otherwise to promote the sale, use orother dealings in this Software without prior written authorizationfrom the X Consortium.*//* * Kerberos V5 authentication scheme * Author: Tom Yu <tlyu@MIT.EDU> * * Mostly snarfed wholesale from the user_user demo in the * krb5 distribution. (At least the checking part) */#include <sys/types.h>#include <sys/socket.h>#ifdef TCPCONN#include <netinet/in.h>#endif#ifdef DNETCONN#include <netdnet/dn.h>#endif#include <arpa/inet.h>#include <krb5/krb5.h>/* 9/93: krb5.h leaks some symbols */#undef BITS32#undef xfree#include <krb5/los-proto.h>#include "X.h"#include "os.h"#include "osdep.h"#include "Xproto.h"#include "Xfuncs.h"#include "dixstruct.h"#include <com_err.h>#include "Xauth.h"extern int (*k5_Vector[256])();extern int SendConnSetup();extern char *display; /* need this to generate rcache name */static XID krb5_id = ~0L;static krb5_principal srvname = NULL; /* service name */static char *ccname = NULL;static char *ktname = NULL; /* key table name */static char kerror[256];/* * tgt_keyproc: * * extract session key from a credentials struct */krb5_error_code tgt_keyproc(keyprocarg, principal, vno, key) krb5_pointer keyprocarg; krb5_principal principal; krb5_kvno vno; krb5_keyblock **key;{ krb5_creds *creds = (krb5_creds *)keyprocarg; return krb5_copy_keyblock(&creds->keyblock, key);}/* * k5_cmpenc: * * compare "encoded" principals */Bool k5_cmpenc(pname, plen, buf) unsigned char *pname; short plen; krb5_data *buf;{ return (plen == buf->length && memcmp(pname, buf->data, plen) == 0);}/* * K5Check: * * This is stage 0 of the krb5 authentication protocol. It * goes through the current credentials cache and extracts the * primary principal and tgt to send to the client, or as * appropriate, extracts from a keytab. * * The packet sent to the client has the following format: * * CARD8 reqType = 2 * CARD8 data = 0 * CARD16 length = total length of packet (in 32 bit units) * CARD16 plen = length of encoded principal following * STRING8 princ = encoded principal * STRING8 ticket = server tgt * * For client-server authentication, the packet is as follows: * * CARD8 reqType = 3 * CARD8 data = 0 * CARD16 length = total length * STRING8 princ = encoded principal of server */XID K5Check(data_length, data, client, reason) unsigned short data_length; char *data; ClientPtr client; char **reason;{ krb5_error_code retval; CARD16 tlen; krb5_principal sprinc, cprinc; krb5_ccache cc; krb5_creds *creds; char *outbuf, *cp; krb5_data princ; register char n; xReq prefix; if (krb5_id == ~0L) return ~0L; if (!ccname && !srvname) return ~0L; if (ccname) { if ((creds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) return ~0L; if (retval = krb5_cc_resolve(ccname, &cc)) return ~0L; bzero((char*)creds, sizeof (krb5_creds)); if (retval = krb5_cc_get_principal(cc, &cprinc)) { krb5_free_creds(creds); krb5_cc_close(cc); return ~0L; } creds->client = cprinc; if (retval = krb5_build_principal_ext(&sprinc, krb5_princ_realm(creds->client)->length, krb5_princ_realm(creds->client)->data, 6, "krbtgt", krb5_princ_realm(creds->client)->length, krb5_princ_realm(creds->client)->data, 0)) { krb5_free_creds(creds); krb5_cc_close(cc); return ~0L; } creds->server = sprinc; retval = krb5_get_credentials(KRB5_GC_CACHED, cc, creds); krb5_cc_close(cc); if (retval) { krb5_free_creds(creds); return ~0L; } if (retval = XauKrb5Encode(cprinc, &princ)) { krb5_free_creds(creds); return ~0L; } tlen = sz_xReq + 2 + princ.length + creds->ticket.length; prefix.reqType = 2; /* opcode = authenticate user-to-user */ } else if (srvname) { if (retval = XauKrb5Encode(srvname, &princ)) { return ~0L; } tlen = sz_xReq + princ.length; prefix.reqType = 3; /* opcode = authenticate client-server */ } prefix.data = 0; /* stage = 0 */ prefix.length = (tlen + 3) >> 2; /* round up to nearest multiple of 4 bytes */ if (client->swapped) { swaps(&prefix.length, n); } if ((cp = outbuf = (char *)malloc(tlen)) == NULL) { if (ccname) { krb5_free_creds(creds); } free(princ.data); return ~0L; } memcpy(cp, &prefix, sz_xReq); cp += sz_xReq; if (ccname) { memcpy(cp, &princ.length, 2); if (client->swapped) { swaps((CARD16 *)cp, n); } cp += 2; } memcpy(cp, princ.data, princ.length); cp += princ.length; free(princ.data); /* we don't need that anymore */ if (ccname) memcpy(cp, creds->ticket.data, creds->ticket.length); WriteToClient(client, tlen, outbuf); free(outbuf); client->requestVector = k5_Vector; /* hack in our dispatch vector */ client->clientState = ClientStateAuthenticating; if (ccname) { ((OsCommPtr)client->osPrivate)->authstate.srvcreds = (pointer)creds; /* save tgt creds */ ((OsCommPtr)client->osPrivate)->authstate.ktname = NULL; ((OsCommPtr)client->osPrivate)->authstate.srvname = NULL; } if (srvname) { ((OsCommPtr)client->osPrivate)->authstate.srvcreds = NULL; ((OsCommPtr)client->osPrivate)->authstate.ktname = (pointer)ktname; ((OsCommPtr)client->osPrivate)->authstate.srvname = (pointer)srvname; } ((OsCommPtr)client->osPrivate)->authstate.stageno = 1; /* next stage is 1 */ return krb5_id;}/* * k5_stage1: * * This gets called out of the dispatcher after K5Check frobs with the * client->requestVector. It accepts the ap_req from the client and verifies * it. In addition, if the client has set AP_OPTS_MUTUAL_REQUIRED, it then * sends an ap_rep to the client to achieve mutual authentication. * * client stage1 packet format is as follows: * * CARD8 reqType = 1 * CARD8 data = ignored * CARD16 length = total length * STRING8 data = the actual ap_req * * stage2 packet sent back to client for mutual authentication: * * CARD8 reqType = 2 * CARD8 data = 2 * CARD16 length = total length * STRING8 data = the ap_rep */int k5_stage1(client) register ClientPtr client;{ long addrlen; krb5_error_code retval, retval2; register char n; struct sockaddr cli_net_addr; xReq prefix; krb5_principal cprinc; krb5_data buf; krb5_creds *creds = (krb5_creds *)((OsCommPtr)client->osPrivate)->authstate.srvcreds; krb5_keyblock *skey; krb5_address cli_addr, **localaddrs = NULL; krb5_tkt_authent *authdat; krb5_ap_rep_enc_part rep; krb5_int32 ctime, cusec; krb5_rcache rcache = NULL; char *cachename = NULL, *rc_type = NULL, *rc_base = "rcX", *kt = NULL; REQUEST(xReq); if (((OsCommPtr)client->osPrivate)->authstate.stageno != 1) { if (creds) krb5_free_creds(creds); return(SendConnSetup(client, "expected Krb5 stage1 packet")); } addrlen = sizeof (cli_net_addr); if (getpeername(((OsCommPtr)client->osPrivate)->fd, &cli_net_addr, &addrlen) == -1) { if (creds) krb5_free_creds(creds); return(SendConnSetup(client, "Krb5 stage1: getpeername failed")); } if (cli_net_addr.sa_family == AF_UNSPEC#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) || cli_net_addr.sa_family == AF_UNIX#endif ) /* assume local host */ { krb5_os_localaddr(&localaddrs); if (!localaddrs || !localaddrs[0]) { if (creds) krb5_free_creds(creds); return(SendConnSetup(client, "Krb5 failed to get localaddrs")); } cli_addr.addrtype = localaddrs[0]->addrtype; cli_addr.length = localaddrs[0]->length; cli_addr.contents = localaddrs[0]->contents; } else { cli_addr.addrtype = cli_net_addr.sa_family; /* the values are compatible */ switch (cli_net_addr.sa_family) {#ifdef TCPCONN case AF_INET: cli_addr.length = sizeof (struct in_addr); cli_addr.contents = (krb5_octet *)&((struct sockaddr_in *)&cli_net_addr)->sin_addr; break;#endif#ifdef DNETCONN case AF_DECnet: cli_addr.length = sizeof (struct dn_naddr); cli_addr.contents = (krb5_octet *)&((struct sockaddr_dn *)&cli_net_addr)->sdn_add; break;#endif default: if (localaddrs) krb5_free_addresses(localaddrs); if (creds) krb5_free_creds(creds); sprintf(kerror, "Krb5 stage1: unknown address family %d from getpeername", cli_net_addr.sa_family); return(SendConnSetup(client, kerror)); } } if ((rcache = (krb5_rcache)malloc(sizeof(*rcache))) == NULL) { if (localaddrs) krb5_free_addresses(localaddrs); if (creds) krb5_free_creds(creds); return(SendConnSetup(client, "malloc bombed for krb5_rcache")); } if ((rc_type = krb5_rc_default_type()) == NULL) rc_type = "dfl"; if (retval = krb5_rc_resolve_type(&rcache, rc_type)) { if (localaddrs) krb5_free_addresses(localaddrs); if (creds) krb5_free_creds(creds); free(rcache); strcpy(kerror, "krb5_rc_resolve_type failed: "); strncat(kerror, error_message(retval), 231); return(SendConnSetup(client, kerror)); } if ((cachename = (char *)malloc(strlen(rc_base) + strlen(display) + 1)) == NULL) { if (localaddrs) krb5_free_addresses(localaddrs); if (creds) krb5_free_creds(creds); free(rcache); return(SendConnSetup(client, "Krb5: malloc bombed for cachename")); } strcpy(cachename, rc_base); strcat(cachename, display); if (retval = krb5_rc_resolve(rcache, cachename)) { if (localaddrs) krb5_free_addresses(localaddrs); if (creds) krb5_free_creds(creds); free(rcache); free(cachename); strcpy(kerror, "krb5_rc_resolve failed: "); strncat(kerror, error_message(retval), 236); return(SendConnSetup(client, kerror)); } free(cachename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -