⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xauth.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 4 页
字号:
/* XAUTH related functions * * Copyright (C) 2001-2002 Colubris Networks * Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc. * Copyright (C) 2003-2004 Xelerance Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * * RCSID $Id: xauth.c,v 1.35 2004/11/30 15:30:24 mcr Exp $ * * This code originally written by Colubris Networks, Inc. * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation * Porting to 2.x by Sean Mathews *///#ifdef XAUTH#include <stdio.h>#include <string.h>#include <stddef.h>#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/queue.h>#include <crypt.h>#include <openswan.h>#include <openswan/ipsec_policy.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "state.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "packet.h"#include "demux.h"	/* needs packet.h */#include "kernel.h"#include "log.h"#include "cookie.h"#include "server.h"#include "spdb.h"#include "timer.h"#include "rnd.h"#include "ipsec_doi.h"	/* needs demux.h and state.h */#include "whack.h"#include "sha1.h"#include "md5.h"#include "crypto.h" /* requires sha1.h and md5.h */#include "paths.h"#include "ike_alg.h"#include "xauth.h"#include "virtual.h"#ifdef HAVE_THREADS#include <pthread.h>#endifstatic stf_statusmodecfg_inI2(struct msg_digest *md);struct paththing pwdfile;extern bool encrypt_message(pb_stream *pbs, struct state *st); /* forward declaration */struct thread_arg{    struct state *st;    chunk_t	name;    chunk_t	password;    chunk_t     connname;};/*** Addresses assigned (usually via MODE_CONFIG) to the Initiator*/struct internal_addr{    ip_address    ipaddr;    ip_address    dns[2];    ip_address    wins[2];  };#ifdef XAUTH_USEPAMstaticint xauth_pam_conv(int num_msg, const struct pam_message **msgm,              struct pam_response **response, void *appdata_ptr);static struct pam_conv conv = {	xauth_pam_conv,	NULL  };/** * Get IP address from a PAM environment variable *  * @param pamh An open PAM filehandle * @param var Environment Variable to get the IP address from.  Usually IPADDR, DNS[12], WINS[12] * @param addr Pointer to var where you want IP address stored * @return int Return code */staticint get_addr(pam_handle_t *pamh,const char *var,ip_address *addr){	const char *c;	int retval;		c = pam_getenv(pamh,var);	if(c == NULL)	{		c="0.0.0.0";	}	retval = inet_pton(AF_INET,c,(void*) &addr->u.v4.sin_addr.s_addr);	addr->u.v4.sin_family = AF_INET;	return (retval > 0);}#endifoakley_auth_t xauth_calcbaseauth(oakley_auth_t baseauth){  switch(baseauth) {  case HybridInitRSA:  case HybridRespRSA:   case XAUTHInitRSA:        case XAUTHRespRSA:          baseauth = OAKLEY_RSA_SIG;    break;      case XAUTHInitDSS:        case XAUTHRespDSS:        case HybridInitDSS:   case HybridRespDSS:     baseauth = OAKLEY_DSS_SIG;    break;      case XAUTHInitPreShared:  case XAUTHRespPreShared:    baseauth = OAKLEY_PRESHARED_KEY;    break;      case XAUTHInitRSAEncryption:                       case XAUTHRespRSAEncryption:    baseauth = OAKLEY_RSA_ENC;    break;      case XAUTHInitRSARevisedEncryption:               case XAUTHRespRSARevisedEncryption:    baseauth = OAKLEY_RSA_ENC_REV;    break;  }    return baseauth;}      /** * Get inside IP address for a connection *  * @param con A currently active connection struct * @param ia internal_addr struct * @return int Return Code */staticint get_internal_addresses(struct connection *con,struct internal_addr *ia){#ifdef XAUTH_USEPAM    int retval;    char str[48];#endif#ifdef NAT_TRAVERSAL /* only NAT-T code lets us do virtual ends */    if (!isanyaddr(&con->spd.that.client.addr))    {	/** assumes IPv4, and also that the mask is ignored */	ia->ipaddr = con->spd.that.client.addr;    }    else#endif    {#ifdef XAUTH_USEPAM	    if(con->pamh == NULL)	    {		    /** Start PAM session, using 'pluto' as our PAM name */		    retval = pam_start("pluto", "user", &conv, &con->pamh);		    memset(ia,0,sizeof(*ia));		    if(retval == PAM_SUCCESS)		    {		            char buf[IDTOA_BUF];			    idtoa(&con->spd.that.id, buf, sizeof(buf));			    if (con->spd.that.id.kind == ID_DER_ASN1_DN)			    {				    /** Keep only the common name, if one exists */				    char *c1, *c2;				    c1 = strstr(buf, "CN=");				    if (c1) {					    c2 = strstr(c1, ", ");					    if (c2) *c2 = '\0';					    memmove(buf, c1+3, strlen(c1) + 1 - 3);				    }			    }			    sprintf(str,"ID=%s", buf);			    pam_putenv(con->pamh,str);			    pam_open_session(con->pamh,0);		    }	    }	    if(con->pamh != NULL)	    {		    /** Put IP addresses from various variables into our                     *  internal address struct */		    get_addr(con->pamh,"IPADDR",&ia->ipaddr);		    get_addr(con->pamh,"DNS1",&ia->dns[0]);		    get_addr(con->pamh,"DNS2",&ia->dns[1]);		    get_addr(con->pamh,"WINS1",&ia->wins[0]);		    get_addr(con->pamh,"WINS2",&ia->wins[1]);	    }#endif    }    return 0;} /** * Compute HASH of Mode Config. * * @param dest  * @param start * @param roof * @param st State structure * @return size_t Length of the HASH */size_txauth_mode_cfg_hash(u_char *dest, const u_char *start, const u_char *roof, const struct state *st){    struct hmac_ctx ctx;    hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a);    hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid));    hmac_update(&ctx, start, roof-start);    hmac_final(dest, &ctx);    DBG(DBG_CRYPT,	DBG_log("XAUTH: HASH computed:"); 	DBG_dump("", dest, ctx.hmac_digest_len));     return ctx.hmac_digest_len;}/** * Mode Config Reply * * Generates a reply stream containing Mode Config information (eg: IP, DNS, WINS) * * @param st State structure * @param resp Type of reply (int) * @param rbody Body of the reply (stream) * @param ap_id ISAMA Identifier  * @return stf_status STF_OK or STF_INTERNAL_ERROR */stf_status modecfg_resp(struct state *st			,unsigned int resp			,pb_stream *rbody			,u_int16_t replytype			,bool hackthat			,u_int16_t ap_id){    unsigned char *r_hash_start,*r_hashval;    /* START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR); */    {      pb_stream hash_pbs;       int np = ISAKMP_NEXT_ATTR;      if (!out_generic(np, &isakmp_hash_desc, rbody, &hash_pbs)) 	return STF_INTERNAL_ERROR;       r_hashval = hash_pbs.cur;	/* remember where to plant value */       if (!out_zero(st->st_oakley.hasher->hash_digest_len, &hash_pbs, "HASH")) 	return STF_INTERNAL_ERROR;       close_output_pbs(&hash_pbs);       r_hash_start = (rbody)->cur;	/* hash from after HASH payload */     }    /* ATTR out */    {	struct  isakmp_mode_attr attrh;	struct isakmp_attribute attr;	pb_stream strattr,attrval;	int attr_type;	struct internal_addr ia;	int dns_idx, wins_idx;	bool dont_advance;	attrh.isama_np = ISAKMP_NEXT_NONE;	attrh.isama_type = replytype;	attrh.isama_identifier = ap_id;	if(!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))	    return STF_INTERNAL_ERROR;		zero(&ia);	get_internal_addresses(st->st_connection, &ia);	if(!isanyaddr(&ia.dns[0]))	/* We got DNS addresses, answer with those */		resp |= LELEM(INTERNAL_IP4_DNS);	else		resp &= ~LELEM(INTERNAL_IP4_DNS);	if(!isanyaddr(&ia.wins[0]))	/* We got WINS addresses, answer with those */		resp |= LELEM(INTERNAL_IP4_NBNS);	else		resp &= ~LELEM(INTERNAL_IP4_NBNS);	if(hackthat) {	    if(memcmp(&st->st_connection->spd.that.client.addr		      ,&ia.ipaddr		      ,sizeof(ia.ipaddr)) != 0)		{		    /* Make the Internal IP address and Netmask as		     * that client address */		    st->st_connection->spd.that.client.addr = ia.ipaddr;		    st->st_connection->spd.that.client.maskbits = 32;		    st->st_connection->spd.that.has_client = TRUE;		}	}	attr_type = 0;	dns_idx = 0;	wins_idx = 0;	while(resp != 0)	{	    dont_advance = FALSE;	    if(resp & 1)	    {			const unsigned char *byte_ptr;		unsigned int len;		/* ISAKMP attr out */		attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;		out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, &attrval);		switch(attr_type)		{		        case INTERNAL_IP4_ADDRESS:		                len = addrbytesptr(&ia.ipaddr, &byte_ptr); 				out_raw(byte_ptr,len,&attrval,"IP4_addr"); 				break;			case INTERNAL_IP4_NETMASK:			    { 				    unsigned int  mask;#if 0				char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};				int t,m=st->st_connection->that.host_addr.maskbit;				for(t=0;t<4;t++)				{				    if(m < 8) 					mask[t] = bits[m];				    else					mask[t] = 0xff;				    m -= 8;				}#endif				     				if (st->st_connection->spd.this.client.maskbits == 0) 					mask = 0; 				else 					mask = 0xffffffff * 1;				out_raw(&mask,4,&attrval,"IP4_mask");			    }			    break;			case INTERNAL_IP4_SUBNET:			    {				char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe};				int t,m=st->st_connection->spd.this.client.maskbits;				for(t=0;t<4;t++)				{				    if(m < 8) 					mask[t] = bits[m];				    else					mask[t] = 0xff;				    m -= 8;				    if(m < 0) m=0;				}				len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);				out_raw(byte_ptr,len,&attrval,"IP4_subnet");				out_raw(mask,sizeof(mask),&attrval,"IP4_submsk"); 				    			    }			    break;		    			case INTERNAL_IP4_DNS: 				len = addrbytesptr(&ia.dns[dns_idx++], &byte_ptr); 				out_raw(byte_ptr,len,&attrval,"IP4_dns");				if(dns_idx < 2 && !isanyaddr(&ia.dns[dns_idx]))				{					dont_advance = TRUE;				} 				break;			case INTERNAL_IP4_NBNS: 				len = addrbytesptr(&ia.wins[wins_idx++], &byte_ptr); 				out_raw(byte_ptr,len,&attrval,"IP4_wins");				if(wins_idx < 2 && !isanyaddr(&ia.wins[wins_idx]))				{					dont_advance = TRUE;				} 				break;		default:		    openswan_log("attempt to send unsupported mode cfg attribute %s."			 , enum_show(&modecfg_attr_names, attr_type));		    break;		}		close_output_pbs(&attrval);	    }	    if (!dont_advance) {		    attr_type++;		    resp >>= 1;	    }	}	close_message(&strattr);    }    xauth_mode_cfg_hash(r_hashval,r_hash_start,rbody->cur,st);        close_message(rbody);    encrypt_message(rbody, st);    return STF_OK;}/** Set MODE_CONFIG data to client.  Pack IP Addresses, DNS, etc... and ship *  * @param st State Structure * @return stf_status */stf_status modecfg_send_set(struct state *st){	pb_stream reply,rbody;	char buf[256];	/* set up reply */	init_pbs(&reply, buf, sizeof(buf), "ModecfgR1");	st->st_state = STATE_MODE_CFG_R1;	/* HDR out */	{		struct isakmp_hdr hdr;		zero(&hdr);	/* default to 0 */		hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;		hdr.isa_np = ISAKMP_NEXT_HASH;		hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;		hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;		memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);		memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);		hdr.isa_msgid = st->st_msgid;		if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody))		{			return STF_INTERNAL_ERROR;		}	}#define MODECFG_SET_ITEM ( LELEM(INTERNAL_IP4_ADDRESS) | LELEM(INTERNAL_IP4_SUBNET) | LELEM(INTERNAL_IP4_NBNS) | LELEM(INTERNAL_IP4_DNS) )	modecfg_resp(st		     ,MODECFG_SET_ITEM		     ,&rbody 		     ,ISAKMP_CFG_SET		     ,TRUE		     ,0/* XXX ID */);#undef MODECFG_SET_ITEM	clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply)			, "ModeCfg set");	/* Transmit */	send_packet(st, "ModeCfg set");	/* RETRANSMIT if Main, SA_REPLACE if Aggressive */	if(st->st_event->ev_type != EVENT_RETRANSMIT	   && st->st_event->ev_type != EVENT_NULL)	{			delete_event(st);		event_schedule(EVENT_RETRANSMIT,EVENT_RETRANSMIT_DELAY_0,st);	}	return STF_OK;}/** Set MODE_CONFIG data to client.  Pack IP Addresses, DNS, etc... and ship *  * @param st State Structure * @return stf_status */stf_status modecfg_start_set(struct state *st){    if(st->st_msgid == 0) {	/* pick a new message id */	st->st_msgid = generate_msgid(st);    }    st->hidden_variables.st_modecfg_vars_set = TRUE;    return modecfg_send_set(st);}/** Send XAUTH credential request (username + password request) * @param st State * @return stf_status */stf_status xauth_send_request(struct state *st){    pb_stream reply;    pb_stream rbody;    char buf[256];    u_char *r_hash_start,*r_hashval;    /* set up reply */    init_pbs(&reply, buf, sizeof(buf), "xauth_buf");    openswan_log("XAUTH: Sending Username/Password request (XAUTH_R0)");    /* this is the beginning of a new exchange */    st->st_msgid = generate_msgid(st);    st->st_state = STATE_XAUTH_R0;    /* HDR out */    {	struct isakmp_hdr hdr;	zero(&hdr);	/* default to 0 */	hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;	hdr.isa_np = ISAKMP_NEXT_HASH;	hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG;	hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION;	memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);	memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE);	hdr.isa_msgid = st->st_msgid;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -