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

📄 keys.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 3 页
字号:
			best = s;	/* list is backwards: take latest in list */		    }		}		else if (match > best_match)		{		    DBG(DBG_CONTROL,			DBG_log("best_match %d>%d best=%p (line=%d)"				, best_match, match				, s, s->secretlineno));		    		    /* this is the best match so far */		    best_match = match;		    best = s;		} else {		    DBG(DBG_CONTROL,			DBG_log("match(%d) was not best_match(%d)"				, match, best_match));		}	    }	}    }    DBG(DBG_CONTROL,	DBG_log("concluding with best_match=%d best=%p (lineno=%d)"		, best_match, best, best? best->secretlineno : -1));		        return best;}/* find the appropriate preshared key (see get_secret). * Failure is indicated by a NULL pointer. * Note: the result is not to be freed by the caller. */const chunk_t *get_preshared_secret(const struct connection *c){    const struct secret *s = get_secret(c, PPK_PSK, FALSE);#ifdef DEBUG    DBG(DBG_PRIVATE,	if (s == NULL)	    DBG_log("no Preshared Key Found");	else	    DBG_dump_chunk("Preshared Key", s->u.preshared_secret);	);#endif    return s == NULL? NULL : &s->u.preshared_secret;}/* check the existence of an RSA private key matching an RSA public * key contained in an X.509 or OpenPGP certificate */boolhas_private_key(cert_t cert){    struct secret *s;    bool has_key = FALSE;    struct pubkey *pubkey;    pubkey = allocate_RSA_public_key(cert);    if(pubkey == NULL) return FALSE;    for (s = secrets; s != NULL; s = s->next)    {	if (s->kind == PPK_RSA &&	    same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))	{	    has_key = TRUE;	    break;	}    }    free_public_key(pubkey);    return has_key;}/* find the appropriate RSA private key (see get_secret). * Failure is indicated by a NULL pointer. */const struct RSA_private_key *get_RSA_private_key(const struct connection *c){    const struct secret *s = get_secret(c, PPK_RSA, TRUE);    return s == NULL? NULL : &s->u.RSA_private_key;}/* digest a secrets file * * The file is a sequence of records.  A record is a maximal sequence of * tokens such that the first, and only the first, is in the first column * of a line. * * Tokens are generally separated by whitespace and are key words, ids, * strings, or data suitable for ttodata(3).  As a nod to convention, * a trailing ":" on what would otherwise be a token is taken as a * separate token.  If preceded by whitespace, a "#" is taken as starting * a comment: it and the rest of the line are ignored. * * One kind of record is an include directive.  It starts with "include". * The filename is the only other token in the record. * If the filename does not start with /, it is taken to * be relative to the directory containing the current file. * * The other kind of record describes a key.  It starts with a * sequence of ids and ends with key information.  Each id * is an IP address, a Fully Qualified Domain Name (which will immediately * be resolved), or @FQDN which will be left as a name. * * The key part can be in several forms. * * The old form of the key is still supported: a simple * quoted strings (with no escapes) is taken as a preshred key. * * The new form starts the key part with a ":". * * For Preshared Key, use the "PSK" keyword, and follow it by a string * or a data token suitable for ttodata(3). * * For RSA Private Key, use the "RSA" keyword, followed by a * brace-enclosed list of key field keywords and data values. * The data values are large integers to be decoded by ttodata(3). * The fields are a subset of those used by BIND 8.2 and have the * same names. *//* process rsa key file protected with optional passphrase which can either be * read from ipsec.secrets or prompted for by using whack */err_tprocess_rsa_keyfile(struct RSA_private_key *rsak, int whackfd){    char filename[BUF_LEN];    err_t ugh = NULL;    rsa_privkey_t *key = NULL;    prompt_pass_t pass;    memset(filename,'\0', BUF_LEN);    memset(pass.secret,'\0', sizeof(pass.secret));    pass.prompt = FALSE;    pass.fd = whackfd;    /* we expect the filename of a PKCS#1 private key file */    if (*tok == '"' || *tok == '\'')  /* quoted filename */	memcpy(filename, tok+1, flp->cur - tok - 2);    else    	memcpy(filename, tok, flp->cur - tok);    if (shift())    {	/* we expect an appended passphrase or passphrase prompt*/	if (tokeqword("%prompt"))	{	    if (pass.fd == NULL_FD)		return "enter a passphrase using ipsec auto --rereadsecrets";	    pass.prompt = TRUE;	}	else if (*tok == '"' || *tok == '\'') /* quoted passphrase */	    memcpy(pass.secret, tok+1, flp->cur - tok - 2);	else	    memcpy(pass.secret, tok, flp->cur - tok);	if (shift())	    ugh = "RSA private key file -- unexpected token after passphrase";    }    key = load_rsa_private_key(filename, &pass);    if (key == NULL)	ugh = "error loading RSA private key file";    else    {	mpz_t u;	u_int i;	for (i = 0; ugh == NULL && i < elemsof(RSA_private_field); i++)	{	    MP_INT *n = (MP_INT *) ((char *)rsak + RSA_private_field[i].offset);	    if (key->field[i].len > 0)	    {		/* PKCS#1 RSA private key format - complete */		n_to_mpz(n, key->field[i].ptr, key->field[i].len);	    }	    else	    {		/* PGP RSA private key format - missing fields */		switch (i)		{		case 5:		/* dP = d mod (p-1) */		    mpz_init(u);		    mpz_sub_ui(u, &rsak->p, 1);		    mpz_mod(n, &rsak->d, u);		    mpz_clear(u);		    break;		case 6:		/* dQ = d mod (q-1) */		    mpz_init(u);		    mpz_sub_ui(u, &rsak->q, 1);		    mpz_mod(n, &rsak->d, u);		    mpz_clear(u);		    break;		case 7:		/* qInv = (q^-1) mod p */		    mpz_invert(n, &rsak->q, &rsak->p);		    if (mpz_cmp_ui(n, 0) < 0)			mpz_add(n, n, &rsak->p);		    passert(mpz_cmp(n, &rsak->p) < 0);		    break;		default:		    break;		}	    }	}	form_keyid(key->field[1], key->field[0], rsak->pub.keyid,		   &rsak->pub.k);	ugh = RSA_private_key_sanity(rsak);	pfree(key->keyobject.ptr);	pfree(key);    }    return ugh;}/* parse PSK from file */static err_tprocess_psk_secret(chunk_t *psk){    err_t ugh = NULL;    if (*tok == '"' || *tok == '\'')    {	clonetochunk(*psk, tok+1, flp->cur - tok  - 2, "PSK");	(void) shift();    }    else    {	char buf[RSA_MAX_ENCODING_BYTES];	/* limit on size of binary representation of key */	size_t sz;	ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz	    , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS);	if (ugh != NULL)	{	    /* ttodata didn't like PSK data */	    ugh = builddiag("PSK data malformed (%s): %s", ugh, tok);	}	else	{	    clonetochunk(*psk, buf, sz, "PSK");	    (void) shift();	}    }    return ugh;}/* Parse fields of RSA private key. * A braced list of keyword and value pairs. * At the moment, each field is required, in order. * The fields come from BIND 8.2's representation */static err_tprocess_rsa_secret(struct RSA_private_key *rsak){    char buf[RSA_MAX_ENCODING_BYTES];	/* limit on size of binary representation of key */    const struct fld *p;    /* save bytes of Modulus and PublicExponent for keyid calculation */    unsigned char ebytes[sizeof(buf)];    unsigned char *eb_next = ebytes;    chunk_t pub_bytes[2];    chunk_t *pb_next = &pub_bytes[0];    for (p = RSA_private_field; p < &RSA_private_field[elemsof(RSA_private_field)]; p++)    {	size_t sz;	err_t ugh;	if (!shift())	{	    return "premature end of RSA key";	}	else if (!tokeqword(p->name))	{	    return builddiag("%s keyword not found where expected in RSA key"		, p->name);	}	else if (!(shift()	&& (!tokeq(":") || shift())))	/* ignore optional ":" */	{	    return "premature end of RSA key";	}	else if (NULL != (ugh = ttodatav(tok, flp->cur - tok	, 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space)	, TTODATAV_SPACECOUNTS)))	{	    /* in RSA key, ttodata didn't like */	    return builddiag("RSA data malformed (%s): %s", ugh, tok);	}	else	{	    MP_INT *n = (MP_INT *) ((char *)rsak + p->offset);	    n_to_mpz(n, buf, sz);	    if (pb_next < &pub_bytes[elemsof(pub_bytes)])	    {		if (eb_next - ebytes + sz > sizeof(ebytes))		    return "public key takes too many bytes";		setchunk(*pb_next, eb_next, sz);		memcpy(eb_next, buf, sz);		eb_next += sz;		pb_next++;	    }#if 0	/* debugging info that compromises security */	    {		size_t sz = mpz_sizeinbase(n, 16);		char buf[RSA_MAX_OCTETS * 2 + 2];	/* ought to be big enough */		passert(sz <= sizeof(buf));		mpz_get_str(buf, 16, n);		loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf);	    }#endif	}    }    /* We require an (indented) '}' and the end of the record.     * We break down the test so that the diagnostic will be     * more helpful.  Some people don't seem to wish to indent     * the brace!     */    if (!shift() || !tokeq("}"))    {	return "malformed end of RSA private key -- indented '}' required";    }    else if (shift())    {	return "malformed end of RSA private key -- unexpected token after '}'";    }    else    {	unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2);	rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;	rsak->pub.keyid[0] = '\0';	/* in case of splitkeytoid failure */	splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len	    , pub_bytes[0].ptr, pub_bytes[0].len	    , rsak->pub.keyid, sizeof(rsak->pub.keyid));	return RSA_private_key_sanity(rsak);    }}/* * get the matching RSA private key belonging to a given X.509 certificate */const struct RSA_private_key*get_x509_private_key(x509cert_t *cert){    struct secret *s;    const struct RSA_private_key *pri = NULL;    cert_t c;    struct pubkey *pubkey;    c.forced = FALSE;    c.type   = CERT_X509_SIGNATURE;    c.u.x509 = cert;    pubkey = allocate_RSA_public_key(c);    if(pubkey == NULL) return NULL;    for (s = secrets; s != NULL; s = s->next)    {	if (s->kind == PPK_RSA &&	    same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa))	{	    pri = &s->u.RSA_private_key;	    break;	}    }    free_public_key(pubkey);    return pri;}#ifdef SMARTCARD/* * process pin read from ipsec.secrets or prompted for it using whack */static err_tprocess_pin(struct secret *s, int whackfd){    smartcard_t *sc;    const char *pin_status = "no";    s->kind = PPK_PIN;    /* looking for the smartcard keyword */    if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0)	 return "PIN keyword must be followed by %smartcard<reader>:<id>";    sc = scx_add(scx_parse_reader_id(tok + strlen(SCX_TOKEN)));    s->u.smartcard = sc;    scx_share(sc);    scx_free_pin(&sc->pin);    sc->valid = FALSE;    if (!shift())	return "PIN statement must be terminated either by <pin code> or %prompt";    if (tokeqword("%prompt"))    {	shift();	/* if whackfd exists, whack will be used to prompt for a pin */	if (whackfd != NULL_FD)	    pin_status = scx_get_pin(sc, whackfd) ? "valid" : "invalid";    }    else    {	/* we read the pin directly from ipsec.secrets */	err_t ugh = process_psk_secret(&sc->pin);	if (ugh != NULL)	    return ugh;	/* verify the pin */	pin_status = scx_verify_pin(sc) ? "valid" : "invalid";    }#ifdef SMARTCARD    openswan_log("  %s PIN for reader: %d, id: %s", pin_status, sc->reader, sc->id);#else    openswan_log("  warning: SMARTCARD support is deactivated in pluto/Makefile!");#endif    return NULL;}#endifstatic voidprocess_secret(struct secret *s, int whackfd){    err_t ugh = NULL;    whackfd = whackfd;  /* shut up compiler */    s->kind = PPK_PSK;	/* default */    if (*tok == '"' || *tok == '\'')    {	/* old PSK format: just a string */	ugh = process_psk_secret(&s->u.preshared_secret);    }    else if (tokeqword("psk"))    {	/* preshared key: quoted string or ttodata format */	ugh = !shift()? "unexpected end of record in PSK"	    : process_psk_secret(&s->u.preshared_secret);    }    else if (tokeqword("rsa"))    {	/* RSA key: the fun begins.	 * A braced list of keyword and value pairs.	 */	s->kind = PPK_RSA;	if (!shift())	{	    ugh = "bad RSA key syntax";	}	else if (tokeq("{"))	{	    ugh = process_rsa_secret(&s->u.RSA_private_key);	}	else	{	   ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);	}	DBG(DBG_CONTROL,	    DBG_log("loaded private key for keyid: %s:%s",		    enum_name(&ppk_names, s->kind),		    s->u.RSA_private_key.pub.keyid));    }    else if (tokeqword("pin"))    {#ifdef SMARTCARD	ugh = process_pin(s, whackfd);#else	ugh = "Smartcard not supported";#endif    }    else    {	ugh = builddiag("unrecognized key format: %s", tok);    }    if (ugh != NULL)    {	loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s"	    , flp->filename, flp->lino, ugh);	pfree(s);    }    else if (flushline("expected record boundary in key"))    {	/* gauntlet has been run: install new secret */	lock_certs_and_keys("process_secret");	s->next = secrets;	secrets = s;	unlock_certs_and_keys("process_secrets");    }}static void process_secrets_file(const char *file_pat, int whackfd);	/* forward declaration */static voidprocess_secret_records(int whackfd){    /* read records from ipsec.secrets and load them into our table */    for (;;)    {	(void)flushline(NULL);	/* silently ditch leftovers, if any */	if (flp->bdry == B_file)	    break;	flp->bdry = B_none;	/* eat the Record Boundary */	(void)shift();	/* get real first token */	if (tokeqword("include"))	{	    /* an include directive */	    char fn[MAX_TOK_LEN];	/* space for filename (I hope) */	    char *p = fn;	    char *end_prefix = strrchr(flp->filename, '/');	    if (!shift())	    {		loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive"		    , flp->filename, flp->lino);		continue;   /* abandon this record */	    }	    /* if path is relative and including file's pathname has	     * a non-empty dirname, prefix this path with that dirname.	     */	    if (tok[0] != '/' && end_prefix != NULL)	    {		size_t pl = end_prefix - flp->filename + 1;		/* "clamp" length to prevent problems now;		 * will be rediscovered and reported later.		 */		if (pl > sizeof(fn))		    pl = sizeof(fn);

⌨️ 快捷键说明

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