Esempio n. 1
0
/**
 * Described in header.
 */
char* path_dirname(const char *path)
{
	char *pos;

	pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;

	if (pos && !pos[1])
	{	/* if path ends with slashes we have to look beyond them */
		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
		{	/* skip trailing slashes */
			pos--;
		}
		pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
	}
	if (!pos)
	{
#ifdef WIN32
		if (path && strlen(path))
		{
			if ((isalpha(path[0]) && path[1] == ':'))
			{	/* if just a drive letter given, return that as dirname */
				return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
			}
		}
#endif
		return strdup(".");
	}
	while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
	{	/* skip superfluous slashes */
		pos--;
	}
	return strndup(path, pos - path + 1);
}
Esempio n. 2
0
/**
 * load the credential from a blob
 */
static void *load_from_blob(chunk_t blob, credential_type_t type, int subtype,
							chunk_t(*cb)(void*,int), void *cb_data,
							x509_flag_t flags)
{
	void *cred = NULL;
	bool pgp = FALSE;

	blob = chunk_clone(blob);
	if (!is_asn1(blob))
	{
		if (pem_to_bin(&blob, cb, cb_data, &pgp) != SUCCESS)
		{
			chunk_clear(&blob);
			return NULL;
		}
		if (pgp && type == CRED_PRIVATE_KEY)
		{
			/* PGP encoded keys are parsed with a KEY_ANY key type, as it
			 * can contain any type of key. However, ipsec.secrets uses
			 * RSA for PGP keys, which is actually wrong. */
			subtype = KEY_ANY;
		}
	}
	/* if CERT_ANY is given, ASN1 encoded blob is handled as X509 */
	if (type == CRED_CERTIFICATE && subtype == CERT_ANY)
	{
		subtype = pgp ? CERT_GPG : CERT_X509;
	}
	cred = lib->creds->create(lib->creds, type, subtype,
							  pgp ? BUILD_BLOB_PGP : BUILD_BLOB_ASN1_DER, blob,
							  flags ? BUILD_X509_FLAG : BUILD_END,
							  flags, BUILD_END);
	chunk_clear(&blob);
	return cred;
}
Esempio n. 3
0
/**
 * Callback function to prompt for private key passwords
 */
CALLBACK(password_cb, shared_key_t*,
	char *prompt, shared_key_type_t type,
	identification_t *me, identification_t *other,
	id_match_t *match_me, id_match_t *match_other)
{
	char *pwd;

	if (type != SHARED_PRIVATE_KEY_PASS)
	{
		return NULL;
	}
	pwd = getpass(prompt);
	if (!pwd || strlen(pwd) == 0)
	{
		return NULL;
	}
	if (match_me)
	{
		*match_me = ID_MATCH_PERFECT;
	}
	if (match_other)
	{
		*match_other = ID_MATCH_PERFECT;
	}
	return shared_key_create(type, chunk_clone(chunk_from_str(pwd)));
}
Esempio n. 4
0
/**
 * Read input data as chunk
 */
static chunk_t read_from_stream(FILE *stream)
{
	char buf[8096];
	size_t len, total = 0;

	while (TRUE)
	{
		len = fread(buf + total, 1, sizeof(buf) - total, stream);
		if (len < (sizeof(buf) - total))
		{
			if (ferror(stream))
			{
				return chunk_empty;
			}
			if (feof(stream))
			{
				return chunk_clone(chunk_create(buf, total + len));
			}
		}
		total += len;
		if (total == sizeof(buf))
		{
			fprintf(stderr, "buffer too small to read input!\n");
			return chunk_empty;
		}
	}
}
Esempio n. 5
0
END_TEST

/*******************************************************************************
 * chunk_create_cat
 */

START_TEST(test_chunk_create_cat)
{
	chunk_t foo, bar;
	chunk_t a, b, c;
	u_char *ptra, *ptrb;

	foo = chunk_from_str("foo");
	bar = chunk_from_str("bar");

	/* to simplify things we use the chunk_cata macro */

	a = chunk_empty;
	b = chunk_empty;
	c = chunk_cata("cc", a, b);
	ck_assert_int_eq(c.len, 0);
	ck_assert(c.ptr != NULL);

	a = foo;
	b = bar;
	c = chunk_cata("cc", a, b);
	ck_assert_int_eq(c.len, 6);
	ck_assert(chunk_equals(c, chunk_from_str("foobar")));

	a = chunk_clone(foo);
	b = chunk_clone(bar);
	c = chunk_cata("mm", a, b);
	ck_assert_int_eq(c.len, 6);
	ck_assert(chunk_equals(c, chunk_from_str("foobar")));

	a = chunk_clone(foo);
	b = chunk_clone(bar);
	ptra = a.ptr;
	ptrb = b.ptr;
	c = chunk_cata("ss", a, b);
	ck_assert_int_eq(c.len, 6);
	ck_assert(chunk_equals(c, chunk_from_str("foobar")));
	/* check memory area of cleared chunk */
	ck_assert(!chunk_equals(foo, chunk_create(ptra, 3)));
	ck_assert(!chunk_equals(bar, chunk_create(ptrb, 3)));
}
static void echo_inbound(void *user, u_int id, chunk_t buf)
{
	test_data_t *data = user;

	ck_assert_int_eq(data->id, id);
	/* count number of bytes, including the header */
	data->bytes += buf.len + sizeof(uint32_t);
	/* echo back data chunk */
	data->s->send(data->s, id, chunk_clone(buf));
}
Esempio n. 7
0
/* decode of RSA pubkey chunk
 * - format specified in RFC 2537 RSA/MD5 Keys and SIGs in the DNS
 * - exponent length in bytes (1 or 3 octets)
 *   + 1 byte if in [1, 255]
 *   + otherwise 0x00 followed by 2 bytes of length
 * - exponent
 * - modulus
 */
err_t
unpack_RSA_public_key(struct RSA_public_key *rsa, const chunk_t *pubkey)
{
    chunk_t exponent;
    chunk_t mod;

    rsa->keyid[0] = '\0';	/* in case of keybolbtoid failure */

    if (pubkey->len < 3)
	return "RSA public key blob way to short";	/* not even room for length! */

    rsa->key_rfc3110 = chunk_clone(*pubkey, "rfc3110 format of public key");

    if (pubkey->ptr[0] != 0x00)
    {
	setchunk(exponent, pubkey->ptr + 1, pubkey->ptr[0]);
    }
    else
    {
	setchunk(exponent, pubkey->ptr + 3
	    , (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]);
    }

    if (pubkey->len - (exponent.ptr - pubkey->ptr) < exponent.len + RSA_MIN_OCTETS_RFC)
	return "RSA public key blob too short";

    mod.ptr = exponent.ptr + exponent.len;
    mod.len = &pubkey->ptr[pubkey->len] - mod.ptr;

    if (mod.len < RSA_MIN_OCTETS)
	return RSA_MIN_OCTETS_UGH;

    if (mod.len > RSA_MAX_OCTETS)
	return RSA_MAX_OCTETS_UGH;

    if (mod.len > pubkey->ptr + pubkey->len - mod.ptr)
       return "RSA public key blob too short";

    n_to_mpz(&rsa->e, exponent.ptr, exponent.len);
    n_to_mpz(&rsa->n, mod.ptr, mod.len);

    keyblobtoid(pubkey->ptr, pubkey->len, rsa->keyid, sizeof(rsa->keyid));

    rsa->k = mpz_sizeinbase(&rsa->n, 2);	/* size in bits, for a start */
    rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE;	/* now octets */

    if (rsa->k != mod.len)
    {
	mpz_clear(&rsa->e);
	mpz_clear(&rsa->n);
	return "RSA modulus shorter than specified";
    }

    return NULL;
}
END_TEST

START_TEST(test_create_own)
{
	chunk_t data = chunk_from_str("foobar");
	bio_reader_t *reader;

	data = chunk_clone(data);
	reader = bio_reader_create_own(data);
	reader->destroy(reader);
}
Esempio n. 9
0
/**
 * create a signed pkcs7 contentInfo object
 */
chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
							   certificate_t *cert, int digest_alg,
							   private_key_t *key)
{
	contentInfo_t pkcs7Data, signedData;
	chunk_t authenticatedAttributes = chunk_empty;
	chunk_t encryptedDigest = chunk_empty;
	chunk_t signerInfo, cInfo, signature, encoding = chunk_empty;;
	signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);

	if (attributes.ptr)
	{
		if (key->sign(key, scheme, attributes, &signature))
		{
			encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
			authenticatedAttributes = chunk_clone(attributes);
			*authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
		}
	}
	else if (data.ptr)
	{
		if (key->sign(key, scheme, data, &signature))
		{
			encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
		}
	}
	signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
				, ASN1_INTEGER_1
				, pkcs7_build_issuerAndSerialNumber(cert)
				, asn1_algorithmIdentifier(digest_alg)
				, authenticatedAttributes
				, asn1_algorithmIdentifier(OID_RSA_ENCRYPTION)
				, encryptedDigest);

	pkcs7Data.type    = OID_PKCS7_DATA;
	pkcs7Data.content = (data.ptr == NULL)? chunk_empty
				: asn1_simple_object(ASN1_OCTET_STRING, data);

	cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
	signedData.type = OID_PKCS7_SIGNED_DATA;
	signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm"
				, ASN1_INTEGER_1
				, asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_alg))
				, pkcs7_build_contentInfo(&pkcs7Data)
				, asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding)
				, asn1_wrap(ASN1_SET, "m", signerInfo));

	cInfo = pkcs7_build_contentInfo(&signedData);
	DBG3(DBG_LIB, "signedData %B", &cInfo);

	free(pkcs7Data.content.ptr);
	free(signedData.content.ptr);
	return cInfo;
}
Esempio n. 10
0
/**
 * read the last serial number from file
 */
static chunk_t read_serial(void)
{
	chunk_t hex, serial = chunk_empty;
	char one[] = {0x01};
	FILE *fd;

	fd = fopen(OPENAC_SERIAL, "r");
	if (fd)
	{
		hex = chunk_alloca(64);
		hex.len = fread(hex.ptr, 1, hex.len, fd);
		if (hex.len)
		{
			/* remove any terminating newline character */
			if (hex.ptr[hex.len-1] == '\n')
			{
				hex.len--;
			}
			serial = chunk_alloca((hex.len / 2) + (hex.len % 2));
			serial = chunk_from_hex(hex, serial.ptr);
		}
		fclose(fd);
	}
	else
	{
		DBG1(DBG_LIB, "  file '%s' does not exist yet - serial number "
			 "set to 01", OPENAC_SERIAL);
	}
	if (!serial.len)
	{
		return chunk_clone(chunk_create(one, 1));
	}
	if (chunk_increment(serial))
	{	/* overflow, prepend 0x01 */
		return chunk_cat("cc", chunk_create(one, 1), serial);
	}
	return chunk_clone(serial);
}
END_TEST

/*******************************************************************************
 * test constructors
 */

START_TEST(test_create)
{
	chunk_t data = chunk_from_str("foobar");
	bio_reader_t *reader;

	data = chunk_clone(data);
	reader = bio_reader_create(data);
	reader->destroy(reader);
	chunk_free(&data);
}
Esempio n. 12
0
/* Read chunk from file.  Return null pointer if fail. */
chunk_ptr chunk_read_legacy(int fd, bool *eofp) {
    unsigned char buf[CHUNK_MAX_SIZE];
    /* Must get enough bytes to read chunk length */
    size_t cnt = 0;
    size_t need_cnt = sizeof(chunk_t);
    while (cnt < need_cnt) {
	ssize_t n = read(fd, &buf[cnt], need_cnt-cnt);
	if (n < 0) {
	    chunk_error("Failed read", NULL);
	    if (eofp)
		*eofp = false;
	    return NULL;
	}
	if (n == 0) {
	    if (eofp)
		*eofp = true;
	    else
		chunk_error("Unexpected EOF", NULL);
	    return NULL;
	}
	cnt += n;
    }
    chunk_ptr creadp = (chunk_ptr) buf;
    size_t len = creadp->length;
    if (len > 1) {
	need_cnt += WORD_BYTES * (len - 1);
	while (cnt < need_cnt) {
	    ssize_t n = read(fd, &buf[cnt], need_cnt-cnt);
	    if (n < 0) {
		chunk_error("Failed read", NULL);
		if (eofp)
		    *eofp = false;
		return NULL;
	    }
	    cnt += n;
	}
    }
    if (eofp)
	*eofp = false;


    return chunk_clone(creadp);
}
Esempio n. 13
0
END_TEST

/*******************************************************************************
 * integer
 */

START_TEST(test_asn1_integer)
{
	typedef struct {
		chunk_t b;
		chunk_t c;
	} testdata_t;

	chunk_t b0 = chunk_from_chars(0x02, 0x01, 0x00);
	chunk_t b1 = chunk_from_chars(0x02, 0x01, 0x7f);
	chunk_t b2 = chunk_from_chars(0x02, 0x02, 0x00, 0x80);

	chunk_t c0 = chunk_empty;
	chunk_t c1 = chunk_from_chars(0x7f);
	chunk_t c2 = chunk_from_chars(0x80);
	chunk_t c3 = chunk_from_chars(0x00, 0x80);

	testdata_t test[] = {
		{ b0, c0 },
		{ b1, c1 },
		{ b2, c2 },
		{ b2, c3 }
	};

	chunk_t a = chunk_empty;
	int i;

	for (i = 0; i < countof(test); i++)
	{
		a = asn1_integer("c", test[i].c);
		ck_assert(chunk_equals(a, test[i].b));
		chunk_free(&a);

		a = asn1_integer("m", chunk_clone(test[i].c));
		ck_assert(chunk_equals(a, test[i].b));
		chunk_free(&a);
	}
}
Esempio n. 14
0
/*
 * Defined in header.
 */
chunk_t asn1_oid_from_string(char *str)
{
	enumerator_t *enumerator;
	u_char buf[64];
	char *end;
	int i = 0, pos = 0, shift;
	u_int val, shifted_val, first = 0;

	enumerator = enumerator_create_token(str, ".", "");
	while (enumerator->enumerate(enumerator, &str))
	{
		val = strtoul(str, &end, 10);
		if (end == str || pos > countof(buf))
		{
			pos = 0;
			break;
		}
		switch (i++)
		{
			case 0:
				first = val;
				break;
			case 1:
				buf[pos++] = first * 40 + val;
				break;
			default:
				shift = 28;		/* sufficient to handle 32 bit node numbers */
				while (shift)
				{
					shifted_val = val >> shift;
					shift -= 7;
					if (shifted_val)	/* do not encode leading zeroes */
					{
						buf[pos++] = 0x80 | (shifted_val & 0x7F);
					}
				}
				buf[pos++] = val & 0x7F;
		}
	}
	enumerator->destroy(enumerator);

	return chunk_clone(chunk_create(buf, pos));
}
Esempio n. 15
0
END_TEST

/*******************************************************************************
 * bitstring
 */

START_TEST(test_asn1_bitstring)
{
	chunk_t a = chunk_empty;
	chunk_t b = chunk_from_chars(0x03, 0x05, 0x00, 0xa1, 0xa2, 0xa3, 0xa4);
	chunk_t c = chunk_from_chars(0xa1, 0xa2, 0xa3, 0xa4);
	chunk_t d = chunk_clone(c);

	a = asn1_bitstring("c", c);
	ck_assert(chunk_equals(a, b));
	chunk_free(&a);

	a = asn1_bitstring("m", d);
	ck_assert(chunk_equals(a, b));
	chunk_free(&a);
}
Esempio n. 16
0
// Return a link, an image, or a literal close bracket.
static cmark_node *handle_close_bracket(subject *subj) {
  bufsize_t initial_pos, after_link_text_pos;
  bufsize_t endurl, starttitle, endtitle, endall;
  bufsize_t sps, n;
  cmark_reference *ref = NULL;
  cmark_chunk url_chunk, title_chunk;
  cmark_chunk url, title;
  bracket *opener;
  cmark_node *inl;
  cmark_chunk raw_label;
  int found_label;
  cmark_node *tmp, *tmpnext;
  bool is_image;

  advance(subj); // advance past ]
  initial_pos = subj->pos;

  // get last [ or ![
  opener = subj->last_bracket;

  if (opener == NULL) {
    return make_str(subj->mem, cmark_chunk_literal("]"));
  }

  if (!opener->active) {
    // take delimiter off stack
    pop_bracket(subj);
    return make_str(subj->mem, cmark_chunk_literal("]"));
  }

  // If we got here, we matched a potential link/image text.
  // Now we check to see if it's a link/image.
  is_image = opener->image;

  after_link_text_pos = subj->pos;

  // First, look for an inline link.
  if (peek_char(subj) == '(' &&
      ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
      ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps, &url_chunk)) > -1)) {

    // try to parse an explicit link:
    endurl = subj->pos + 1 + sps + n;
    starttitle = endurl + scan_spacechars(&subj->input, endurl);

    // ensure there are spaces btw url and title
    endtitle = (starttitle == endurl)
                   ? starttitle
                   : starttitle + scan_link_title(&subj->input, starttitle);

    endall = endtitle + scan_spacechars(&subj->input, endtitle);

    if (peek_at(subj, endall) == ')') {
      subj->pos = endall + 1;

      title_chunk =
          cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
      url = cmark_clean_url(subj->mem, &url_chunk);
      title = cmark_clean_title(subj->mem, &title_chunk);
      cmark_chunk_free(subj->mem, &url_chunk);
      cmark_chunk_free(subj->mem, &title_chunk);
      goto match;

    } else {
      // it could still be a shortcut reference link
      subj->pos = after_link_text_pos;
    }
  }

  // Next, look for a following [link label] that matches in refmap.
  // skip spaces
  raw_label = cmark_chunk_literal("");
  found_label = link_label(subj, &raw_label);
  if (!found_label) {
    // If we have a shortcut reference link, back up
    // to before the spacse we skipped.
    subj->pos = initial_pos;
  }

  if ((!found_label || raw_label.len == 0) && !opener->bracket_after) {
    cmark_chunk_free(subj->mem, &raw_label);
    raw_label = cmark_chunk_dup(&subj->input, opener->position,
                                initial_pos - opener->position - 1);
    found_label = true;
  }

  if (found_label) {
    ref = cmark_reference_lookup(subj->refmap, &raw_label);
    cmark_chunk_free(subj->mem, &raw_label);
  }

  if (ref != NULL) { // found
    url = chunk_clone(subj->mem, &ref->url);
    title = chunk_clone(subj->mem, &ref->title);
    goto match;
  } else {
    goto noMatch;
  }

noMatch:
  // If we fall through to here, it means we didn't match a link:
  pop_bracket(subj); // remove this opener from delimiter list
  subj->pos = initial_pos;
  return make_str(subj->mem, cmark_chunk_literal("]"));

match:
  inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
  inl->as.link.url = url;
  inl->as.link.title = title;
  cmark_node_insert_before(opener->inl_text, inl);
  // Add link text:
  tmp = opener->inl_text->next;
  while (tmp) {
    tmpnext = tmp->next;
    cmark_node_append_child(inl, tmp);
    tmp = tmpnext;
  }

  // Free the bracket [:
  cmark_node_free(opener->inl_text);

  process_emphasis(subj, opener->previous_delimiter);
  pop_bracket(subj);

  // Now, if we have a link, we also want to deactivate earlier link
  // delimiters. (This code can be removed if we decide to allow links
  // inside links.)
  if (!is_image) {
    opener = subj->last_bracket;
    while (opener != NULL) {
      if (!opener->image) {
        if (!opener->active) {
          break;
        } else {
          opener->active = false;
        }
      }
      opener = opener->previous;
    }
  }

  return NULL;
}
Esempio n. 17
0
/**
 * Determine the type of the attribute and its value
 */
static bool parse_attributes(char *name, char *value, value_type_t *value_type,
							 configuration_attribute_type_t *type,
							 configuration_attribute_type_t *type_ip6,
							 chunk_t *blob)
{
	host_t *addr = NULL, *mask = NULL;
	chunk_t addr_chunk, mask_chunk, blob_next;
	char *text = "", *pos_addr, *pos_mask, *pos_next, *endptr;
	int i;

	switch (*value_type)
	{
		case VALUE_STRING:
			*blob = chunk_create(value, strlen(value));
			*blob = chunk_clone(*blob);
			break;
		case VALUE_HEX:
			*blob = chunk_from_hex(chunk_create(value, strlen(value)), NULL);
			break;
		case VALUE_ADDR:
			addr = host_create_from_string(value, 0);
			if (addr == NULL)
			{
				fprintf(stderr, "invalid IP address: '%s'.\n", value);
				return FALSE;
			}
			addr_chunk = addr->get_address(addr);
			*blob = chunk_clone(addr_chunk);
			break;
		case VALUE_SUBNET:
			*blob = chunk_empty;
			pos_next = value;

			do
			{
				pos_addr = pos_next;
				pos_next = strchr(pos_next, ',');
				if (pos_next)
				{
					*pos_next = '\0';
					pos_next += 1;
				}
				pos_mask = strchr(pos_addr, '/');
				if (pos_mask == NULL)
				{
					fprintf(stderr, "invalid IPv4 subnet: '%s'.\n", pos_addr);
					free(blob->ptr);
					return FALSE;
				}
				*pos_mask = '\0';
				pos_mask += 1;
				addr = host_create_from_string(pos_addr, 0);
				mask = host_create_from_string(pos_mask, 0);
				if (addr == NULL || addr->get_family(addr) != AF_INET ||
					mask == NULL || mask->get_family(addr) != AF_INET)
				{
					fprintf(stderr, "invalid IPv4 subnet: '%s/%s'.\n",
									pos_addr, pos_mask);
					DESTROY_IF(addr);
					DESTROY_IF(mask);
					free(blob->ptr);
					return FALSE;
				}
				addr_chunk = addr->get_address(addr);
				mask_chunk = mask->get_address(mask);
				blob_next = chunk_alloc(blob->len + UNITY_NETWORK_LEN);
				memcpy(blob_next.ptr, blob->ptr, blob->len);
				pos_addr = blob_next.ptr + blob->len;
				memset(pos_addr, 0x00, UNITY_NETWORK_LEN);
				memcpy(pos_addr,     addr_chunk.ptr, 4);
				memcpy(pos_addr + 4, mask_chunk.ptr, 4);
				addr->destroy(addr);
				addr = NULL;
				mask->destroy(mask);
				chunk_free(blob);
				*blob = blob_next;
			}
			while (pos_next);
			break;
		case VALUE_NONE:
			*blob = chunk_empty;
			break;
	}

	/* init the attribute type */
	*type     = 0;
	*type_ip6 = 0;

	for (i = 0; i < countof(attr_info); i++)
	{
		if (strcaseeq(name, attr_info[i].keyword))
		{
			*type      = attr_info[i].type;
			*type_ip6  = attr_info[i].type_ip6;

			if (*value_type == VALUE_NONE)
			{
				*value_type = attr_info[i].value_type;
				return TRUE;
			}

			if (*value_type != attr_info[i].value_type &&
				*value_type != VALUE_HEX)
			{
				switch (attr_info[i].value_type)
				{
					case VALUE_STRING:
						text = "a string";
						break;
					case VALUE_HEX:
						text = "a hex";
						break;
					case VALUE_ADDR:
						text = "an IP address";
						break;
					case VALUE_SUBNET:
						text = "a subnet";
						break;
					case VALUE_NONE:
						text = "no";
						break;
				}
				fprintf(stderr, "the %s attribute requires %s value.\n",
								 name, text);
				DESTROY_IF(addr);
				free(blob->ptr);
				return FALSE;
			}

			if (*value_type == VALUE_ADDR)
			{
				*type = (addr->get_family(addr) == AF_INET) ?
							attr_info[i].type : attr_info[i].type_ip6;
				addr->destroy(addr);
			}
			else if (*value_type == VALUE_HEX)
			{
				*value_type = attr_info[i].value_type;

				if (*value_type == VALUE_ADDR)
				{
					if (blob->len == 16)
					{
						*type = attr_info[i].type_ip6;
					}
					else if (blob->len != 4)
					{
						fprintf(stderr, "the %s attribute requires "
										"a valid IP address.\n", name);
						free(blob->ptr);
						return FALSE;
					}
				}
			}
			return TRUE;
		}
	}

	/* clean up */
	DESTROY_IF(addr);

	/* is the attribute type numeric? */
	*type = strtol(name, &endptr, 10);

	if (*endptr != '\0')
	{
		fprintf(stderr, "the %s attribute is not recognized.\n", name);
		free(blob->ptr);
		return FALSE;
	}
	if (*type < 1 || *type > 32767)
	{
		fprintf(stderr, "the attribute type must lie in the range 1..32767.\n");
		free(blob->ptr);
		return FALSE;
	}
	if (*value_type == VALUE_NONE)
	{
		*value_type = VALUE_HEX;
	}
	return TRUE;
}
Esempio n. 18
0
chunk_ptr chunk_read(int fd, bool* eofp)
{
    if (fd > maxfd)
    {
        // on first call, we zero the buffer set
        if (maxfd == 0)
        {
            FD_ZERO(&buf_set);
            FD_ZERO(&in_set);
        }
        maxfd = fd;
    }

    buf_node* curr_node = NULL;
    buf_node* temp_node = NULL;
    //create new head
    if (buf_list_head == NULL) {
        buf_list_head = calloc_or_fail(sizeof(buf_node), 1,
				       "chunk_read create head");
        buf_list_head->fd = fd;
#if RPT >= 5
        report(5, "created a node for fd %d as head\n", fd);
#endif
        buf_list_head->length = 0;
        buf_list_head->location = 0;
        buf_list_head->buf = calloc_or_fail(CHUNK_MAX_SIZE, 2,
					    "chunk_read create head buf");
        curr_node = buf_list_head;
    }
    // search for the fd in the buffer list, if it exists
    else {
        temp_node = buf_list_head;
        while (temp_node != NULL && curr_node == NULL) {
            if (fd == temp_node->fd) {
                curr_node = temp_node;
#if RPT >= 5
                report(5, "found node for fd %d\n", fd);
#endif
            }
            temp_node = temp_node->next;
        }
    }
    // if it doesn't exist, create the new fd buffer at the head of the list
    if (curr_node == NULL) {
        curr_node = calloc_or_fail(sizeof(buf_node), 1, "chunk_read create node");
        curr_node->fd = fd;
        curr_node->length = 0;
        curr_node->location = 0;
        curr_node->next = buf_list_head;
        curr_node->buf = calloc_or_fail(CHUNK_MAX_SIZE, 2,
					"chunk_read create head buf");
#if RPT >= 5
        report(5, "created a node for fd %d at head\n", fd);
#endif
        buf_list_head = curr_node;
    }

    // if we can copy to the beginning, then we copy to the beginning
    // (if the read point is past the beginning, and if the end of
    // the buffered data is past the midway point of the buffer)
    if (curr_node->length + curr_node->location >= CHUNK_MAX_SIZE
	&& curr_node->location > 0)
    {
        memmove(curr_node->buf, (char *)(curr_node->buf + curr_node->location),
		curr_node->length);
        curr_node->location = 0;
    }

    // read if possible - if there is space, if the inset contains it, and if we
    // want to use buffering (otherwise we don't want random buffer refills)
    if (((curr_node->length + curr_node->location) < CHUNK_MAX_SIZE)
	&& bufferReadBool && !(!(FD_ISSET(fd, &in_set))) )
    {
#if RPT >= 5
        report(5, "reading for %d\n", curr_node->fd);
#endif
        ssize_t n = read(curr_node->fd,
			 curr_node->buf + curr_node->location + curr_node->length,
			 CHUNK_MAX_SIZE);
        curr_node->length += n;
    }

#if RPT >= 5
    report(5, "about to get header for %d\n", fd);
#endif
    // get header of chunk
    size_t need_cnt = sizeof(chunk_t);
    unsigned char buf[CHUNK_MAX_SIZE];
    unsigned char* buf_ptr = (unsigned char*)buf;
    ssize_t n = buf_read(curr_node, eofp, buf_ptr, need_cnt);
    //ssize_t n = read(curr_node->fd, buf, need_cnt);
    if (n <= 0)
    {
	return NULL;
    }
#if RPT >= 5
    report(5, "about to get rest of chunk for fd %d\n", fd);
#endif
    // get rest of chunk
    chunk_ptr creadp = (chunk_ptr) buf_ptr;
    size_t len = creadp->length;
#if RPT >= 5
    report(5, "len needed: %d", len);
#endif
    if (len > 1) {
	need_cnt = WORD_BYTES * (len - 1);
#if RPT >= 5
        report(5, "head buf pointer at %p", buf_ptr);
#endif
        buf_ptr = (unsigned char *)(buf_ptr + n);
#if RPT >= 5
        report(5, "moved pointer to %p for rest", buf_ptr);
#endif
        ssize_t n = buf_read(curr_node, eofp, buf_ptr, need_cnt);
        //ssize_t n = read(curr_node->fd, buf_ptr, need_cnt);

        if (n < 0) {
            chunk_error("Failed read", NULL);
	    if (eofp)
		*eofp = false;
            return NULL;
        }
    }

#if RPT >= 5
    report(5, "exiting chunk_read_buffered_builtin!\n");
#endif
    if (eofp)
	*eofp = false;
    return chunk_clone(creadp);
}
Esempio n. 19
0
/**
 * Add ITA Device ID attribute to the send queue
 */
static void add_device_id(imc_msg_t *msg)
{
	pa_tnc_attr_t *attr;
	chunk_t value = chunk_empty, keyid;
	char *name, *device_id, *cert_path;
	certificate_t *cert = NULL;
	public_key_t *pubkey;

	/* Get the device ID as a character string */
	device_id = lib->settings->get_str(lib->settings,
						"%s.plugins.imc-os.device_id", NULL, lib->ns);
	if (device_id)
	{
		value = chunk_clone(chunk_from_str(device_id));
	}

	if (value.len == 0)
	{
		/* Derive the device ID from a raw public key */
		cert_path = lib->settings->get_str(lib->settings,
							"%s.plugins.imc-os.device_pubkey", NULL, lib->ns);
		if (cert_path)
		{
			cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
									  CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
									  cert_path, BUILD_END);
			if (cert)
			{
				DBG2(DBG_IMC, "loaded device public key from '%s'", cert_path);
			}
			else
			{
				DBG1(DBG_IMC, "loading device public key from '%s' failed",
							   cert_path);
			}
		}

		if (!cert)
		{
			/* Derive the device ID from the public key contained in a certificate */
			cert_path = lib->settings->get_str(lib->settings,
								"%s.plugins.imc-os.device_cert", NULL, lib->ns);
			if (cert_path)
			{
				cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
										  CERT_X509, BUILD_FROM_FILE,
										  cert_path, BUILD_END);
				if (cert)
				{
					DBG2(DBG_IMC, "loaded device certificate from '%s'", cert_path);
				}
				else
				{
					DBG1(DBG_IMC, "loading device certificate from '%s' failed",
								   cert_path);
				}
			}
		}

		/* Compute the SHA-1 keyid of the retrieved device public key */
		if (cert)
		{
			pubkey = cert->get_public_key(cert);
			if (pubkey)
			{
				if (pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_INFO_SHA1,
											&keyid))
				{
					value = chunk_to_hex(keyid, NULL, FALSE);
				}
				pubkey->destroy(pubkey);
			}
			cert->destroy(cert);
		}
	}

	if (value.len == 0)
	{
		/* Derive the device ID from some unique OS settings */
		name = os->get_type(os) == OS_TYPE_ANDROID ?
					  "android_id" : "/var/lib/dbus/machine-id";
		value = os->get_setting(os, name);

		/* Trim trailing newline character */
		if (value.len > 0 && value.ptr[value.len - 1] == '\n')
		{
			value.len--;
		}
	}

	if (value.len == 0)
	{
		DBG1(DBG_IMC, "no device ID available");
		return;
	}

	DBG1(DBG_IMC, "device ID is %.*s", value.len, value.ptr);
	attr = ita_attr_device_id_create(value);
	msg->add_attribute(msg, attr);
	free(value.ptr);
}
Esempio n. 20
0
bool send_op(chunk_ptr msg) {
    dword_t dh = chunk_get_dword(msg, 0);
    unsigned agent = msg_get_dheader_agent(dh);
    unsigned code = msg_get_dheader_code(dh);

    if (code == MSG_OPERATION) {
	agent_stat_counter[STATA_OPERATION_TOTAL]++;
	if (self_route && agent == own_agent) {
	    agent_stat_counter[STATA_OPERATION_LOCAL]++;
#if RPT >= 6
	    word_t id = msg_get_dheader_op_id(dh);
	    report(6, "Routing operator with id 0x%lx to self", id);
#endif
	    receive_operation(chunk_clone(msg));
	    return true;
	}
    }
    if (code == MSG_OPERAND) {
	agent_stat_counter[STATA_OPERAND_TOTAL]++;
	if (self_route && agent == own_agent && !isclient) {
	    agent_stat_counter[STATA_OPERAND_LOCAL]++;
#if RPT >= 6
	    word_t id = msg_get_dheader_op_id(dh);
	    report(6, "Routing operand with id 0x%lx to self", id);
#endif
	    receive_operand(chunk_clone(msg));
	    return true;
	}
    }
    // Try to send to a local router if possible
    int rfd;
    if (local_router_fd == -1)
    {
        unsigned idx = random() % nrouters;
        rfd = router_fd_array[idx];
#if RPT >= 5
	word_t id = msg_get_dheader_op_id(dh);
        report(5,
"Sending message with id 0x%x through router %u (fd %d)", id, idx, rfd);
#endif
    }
    else
    {
        rfd = local_router_fd;
#if RPT >= 5
	word_t id = msg_get_dheader_op_id(dh);
        report(5,
"Sending message with id 0x%x through the local router (fd %d)", id, rfd);
#endif
    }

    bool ok = chunk_write(rfd, msg);
    if (ok) {
#if RPT >= 5
	report(5, "Message sent");
#endif
    } else {
	err(false, "Failed");
    }
    return ok;
}
Esempio n. 21
0
static bool do_test_mct(test_vector_t *test)
{
	crypter_t *crypter;
	chunk_t prev, *input, *output;
	int i, j;

	crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC,
										  test->key.len);
	if (!crypter)
	{
		DBG1(DBG_APP, "algorithm %N or key length (%d bits) not supported",
			 encryption_algorithm_names, ENCR_AES_CBC, test->key.len * 8);
		return FALSE;
	}
	input = ctx.decrypt ? &test->cipher : &test->plain;
	output = ctx.decrypt ? &test->plain : &test->cipher;
	if (crypter->get_block_size(crypter) != input->len)
	{
		DBG1(DBG_APP, "MCT only works for input with a length of one block");
		crypter->destroy(crypter);
		return FALSE;
	}
	prev = chunk_alloca(input->len);
	/* assume initial IV as previous output */
	*output = chunk_clone(test->iv);
	for (i = 0; i < 100; i++)
	{
		if (i > 0)
		{	/* we copied the original lines already */
			fprintf(ctx.out, "COUNT = %d\n", i);
			fprintf(ctx.out, "KEY = %+B\n", &test->key);
			fprintf(ctx.out, "IV = %+B\n", &test->iv);
			fprintf(ctx.out, "%s = %+B\n",
					ctx.decrypt ? "CIPHERTEXT" : "PLAINTEXT", input);
		}
		if (!crypter->set_key(crypter, test->key))
		{
			DBG1(DBG_APP, "failed to set key");
			return FALSE;
		}
		for (j = 0; j < 1000; j++)
		{
			/* store previous output as it is used as input after next */
			memcpy(prev.ptr, output->ptr, prev.len);
			chunk_free(output);
			if (!do_crypt(crypter, test))
			{
				crypter->destroy(crypter);
				return FALSE;
			}
			/* prepare the next IV (our API does not allow incremental calls) */
			if (ctx.decrypt)
			{
				memcpy(test->iv.ptr, input->ptr, test->iv.len);
			}
			else
			{
				memcpy(test->iv.ptr, output->ptr, test->iv.len);
			}
			/* the previous output is the next input */
			memcpy(input->ptr, prev.ptr, input->len);
		}
		fprintf(ctx.out, "%s = %+B\n\n",
				ctx.decrypt ? "PLAINTEXT" : "CIPHERTEXT", output);
		/* derive key for next round */
		switch (test->key.len)
		{
			case 16:
				memxor(test->key.ptr, output->ptr, output->len);
				break;
			case 24:
				memxor(test->key.ptr, prev.ptr + 8, 8);
				memxor(test->key.ptr + 8, output->ptr, output->len);
				break;
			case 32:
				memxor(test->key.ptr, prev.ptr, prev.len);
				memxor(test->key.ptr + prev.len, output->ptr, output->len);
				break;
		}
		/* the current output is used as IV for the next round */
		memcpy(test->iv.ptr, output->ptr, test->iv.len);
	}
	crypter->destroy(crypter);
	/* we return FALSE as we print the output ourselves */
	return FALSE;
}
Esempio n. 22
0
/**
 * create the lease query using the filter string
 */
static enumerator_t *create_lease_query(char *filter, array_t **to_free)
{
	enumerator_t *query;
	chunk_t id_chunk = chunk_empty, addr_chunk = chunk_empty;
	id_type_t id_type = 0;
	u_int tstamp = 0;
	bool online = FALSE, valid = FALSE, expired = FALSE;
	char *value, *pos, *pool = NULL;
	enum {
		FIL_POOL = 0,
		FIL_ID,
		FIL_ADDR,
		FIL_TSTAMP,
		FIL_STATE,
	};
	char *const token[] = {
		[FIL_POOL] = "pool",
		[FIL_ID] = "id",
		[FIL_ADDR] = "addr",
		[FIL_TSTAMP] = "tstamp",
		[FIL_STATE] = "status",
		NULL
	};

	/* if the filter string contains a distinguished name as a ID, we replace
	 * ", " by "/ " in order to not confuse the getsubopt parser */
	pos = filter;
	while ((pos = strchr(pos, ',')))
	{
		if (pos[1] == ' ')
		{
			pos[0] = '/';
		}
		pos++;
	}

	while (filter && *filter != '\0')
	{
		switch (getsubopt(&filter, token, &value))
		{
			case FIL_POOL:
				if (value)
				{
					pool = value;
				}
				break;
			case FIL_ID:
				if (value)
				{
					identification_t *id;

					id = identification_create_from_string(value);
					id_type = id->get_type(id);
					id_chunk = chunk_clone(id->get_encoding(id));
					array_insert_create(to_free, ARRAY_TAIL, id_chunk.ptr);
					id->destroy(id);
				}
				break;
			case FIL_ADDR:
				if (value)
				{
					host_t *addr;

					addr = host_create_from_string(value, 0);
					if (!addr)
					{
						fprintf(stderr, "invalid 'addr' in filter string.\n");
						exit(EXIT_FAILURE);
					}
					addr_chunk = chunk_clone(addr->get_address(addr));
					array_insert_create(to_free, ARRAY_TAIL, addr_chunk.ptr);
					addr->destroy(addr);
				}
				break;
			case FIL_TSTAMP:
				if (value)
				{
					tstamp = atoi(value);
				}
				if (tstamp == 0)
				{
					online = TRUE;
				}
				break;
			case FIL_STATE:
				if (value)
				{
					if (streq(value, "online"))
					{
						online = TRUE;
					}
					else if (streq(value, "valid"))
					{
						valid = TRUE;
					}
					else if (streq(value, "expired"))
					{
						expired = TRUE;
					}
					else
					{
						fprintf(stderr, "invalid 'state' in filter string.\n");
						exit(EXIT_FAILURE);
					}
				}
				break;
			default:
				fprintf(stderr, "invalid filter string.\n");
				exit(EXIT_FAILURE);
				break;
		}
	}
	query = db->query(db,
				"SELECT name, addresses.address, identities.type, "
				"identities.data, leases.acquired, leases.released, timeout "
				"FROM leases JOIN addresses ON leases.address = addresses.id "
				"JOIN pools ON addresses.pool = pools.id "
				"JOIN identities ON leases.identity = identities.id "
				"WHERE (? OR name = ?) "
				"AND (? OR (identities.type = ? AND identities.data = ?)) "
				"AND (? OR addresses.address = ?) "
				"AND (? OR (? >= leases.acquired AND (? <= leases.released))) "
				"AND (? OR leases.released > ? - timeout) "
				"AND (? OR leases.released < ? - timeout) "
				"AND ? "
				"UNION "
				"SELECT name, address, identities.type, identities.data, "
				"acquired, released, timeout FROM addresses "
				"JOIN pools ON addresses.pool = pools.id "
				"JOIN identities ON addresses.identity = identities.id "
				"WHERE ? AND released = 0 "
				"AND (? OR name = ?) "
				"AND (? OR (identities.type = ? AND identities.data = ?)) "
				"AND (? OR address = ?)",
				DB_INT, pool == NULL, DB_TEXT, pool,
				DB_INT, !id_chunk.ptr,
					DB_INT, id_type,
					DB_BLOB, id_chunk,
				DB_INT, !addr_chunk.ptr,
					DB_BLOB, addr_chunk,
				DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
				DB_INT, !valid, DB_INT, time(NULL),
				DB_INT, !expired, DB_INT, time(NULL),
				DB_INT, !online,
				/* union */
				DB_INT, !(valid || expired),
				DB_INT, pool == NULL, DB_TEXT, pool,
				DB_INT, !id_chunk.ptr,
					DB_INT, id_type,
					DB_BLOB, id_chunk,
				DB_INT, !addr_chunk.ptr,
					DB_BLOB, addr_chunk,
				/* res */
				DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
	return query;
}
Esempio n. 23
0
/**
 * Converts a PEM encoded file into its binary form (RFC 1421, RFC 934)
 */
static status_t pem_to_bin(chunk_t *blob, bool *pgp)
{
	typedef enum {
		PEM_PRE    = 0,
		PEM_MSG    = 1,
		PEM_HEADER = 2,
		PEM_BODY   = 3,
		PEM_POST   = 4,
		PEM_ABORT  = 5
	} state_t;

	encryption_algorithm_t alg = ENCR_UNDEFINED;
	size_t key_size = 0;
	bool encrypted = FALSE;
	state_t state  = PEM_PRE;
	chunk_t src    = *blob;
	chunk_t dst    = *blob;
	chunk_t line   = chunk_empty;
	chunk_t iv     = chunk_empty;
	u_char iv_buf[HASH_SIZE_MD5];
	status_t status = NOT_FOUND;
	enumerator_t *enumerator;
	shared_key_t *shared;

	dst.len = 0;
	iv.ptr = iv_buf;
	iv.len = 0;

	while (fetchline(&src, &line))
	{
		if (state == PEM_PRE)
		{
			if (find_boundary("BEGIN", &line))
			{
				state = PEM_MSG;
			}
			continue;
		}
		else
		{
			if (find_boundary("END", &line))
			{
				state = PEM_POST;
				break;
			}
			if (state == PEM_MSG)
			{
				state = PEM_HEADER;
				if (memchr(line.ptr, ':', line.len) == NULL)
				{
					state = PEM_BODY;
				}
			}
			if (state == PEM_HEADER)
			{
				err_t ugh = NULL;
				chunk_t name  = chunk_empty;
				chunk_t value = chunk_empty;

				/* an empty line separates HEADER and BODY */
				if (line.len == 0)
				{
					state = PEM_BODY;
					continue;
				}

				/* we are looking for a parameter: value pair */
				DBG2(DBG_ASN, "  %.*s", (int)line.len, line.ptr);
				ugh = extract_parameter_value(&name, &value, &line);
				if (ugh != NULL)
				{
					continue;
				}
				if (match("Proc-Type", &name) && *value.ptr == '4')
				{
					encrypted = TRUE;
				}
				else if (match("DEK-Info", &name))
				{
					chunk_t dek;

					if (!extract_token(&dek, ',', &value))
					{
						dek = value;
					}
					if (match("DES-EDE3-CBC", &dek))
					{
						alg = ENCR_3DES;
						key_size = 24;
					}
					else if (match("AES-128-CBC", &dek))
					{
						alg = ENCR_AES_CBC;
						key_size = 16;
					}
					else if (match("AES-192-CBC", &dek))
					{
						alg = ENCR_AES_CBC;
						key_size = 24;
					}
					else if (match("AES-256-CBC", &dek))
					{
						alg = ENCR_AES_CBC;
						key_size = 32;
					}
					else
					{
						DBG1(DBG_ASN, "  encryption algorithm '%.*s'"
							 " not supported", (int)dek.len, dek.ptr);
						return NOT_SUPPORTED;
					}
					if (!eat_whitespace(&value) || value.len > 2*sizeof(iv_buf))
					{
						return PARSE_ERROR;
					}
					iv = chunk_from_hex(value, iv_buf);
				}
			}
			else /* state is PEM_BODY */
			{
				chunk_t data;

				/* remove any trailing whitespace */
				if (!extract_token(&data ,' ', &line))
				{
					data = line;
				}

				/* check for PGP armor checksum */
				if (*data.ptr == '=')
				{
					*pgp = TRUE;
					data.ptr++;
					data.len--;
					DBG2(DBG_ASN, "  armor checksum: %.*s", (int)data.len,
						 data.ptr);
					continue;
				}

				if (blob->len - dst.len < data.len / 4 * 3)
				{
					state = PEM_ABORT;
				}
				data = chunk_from_base64(data, dst.ptr);

				dst.ptr += data.len;
				dst.len += data.len;
			}
		}
	}
	/* set length to size of binary blob */
	blob->len = dst.len;

	if (state != PEM_POST)
	{
		DBG1(DBG_LIB, "  file coded in unknown format, discarded");
		return PARSE_ERROR;
	}
	if (!encrypted)
	{
		return SUCCESS;
	}

	enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
											SHARED_PRIVATE_KEY_PASS, NULL, NULL);
	while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
	{
		chunk_t passphrase, chunk;

		passphrase = shared->get_key(shared);
		chunk = chunk_clone(*blob);
		status = pem_decrypt(&chunk, alg, key_size, iv, passphrase);
		if (status == SUCCESS)
		{
			memcpy(blob->ptr, chunk.ptr, chunk.len);
			blob->len = chunk.len;
		}
		free(chunk.ptr);
		if (status != INVALID_ARG)
		{	/* try again only if passphrase invalid */
			break;
		}
	}
	enumerator->destroy(enumerator);
	return status;
}
int main(int argc, char *argv[])
{
	char *address = NULL, *identity = "%any", *secret = NULL;
	int port = PT_TLS_PORT;

	init();

	while (TRUE)
	{
		struct option long_opts[] = {
			{"help",		no_argument,			NULL,		'h' },
			{"connect",		required_argument,		NULL,		'c' },
			{"client",		required_argument,		NULL,		'i' },
			{"secret",		required_argument,		NULL,		's' },
			{"port",		required_argument,		NULL,		'p' },
			{"cert",		required_argument,		NULL,		'x' },
			{"key",			required_argument,		NULL,		'k' },
			{"mutual",		no_argument,			NULL,		'm' },
			{"quiet",		no_argument,			NULL,		'q' },
			{"debug",		required_argument,		NULL,		'd' },
			{"optionsfrom",	required_argument,		NULL,		'+' },
			{0,0,0,0 }
		};
		switch (getopt_long(argc, argv, "", long_opts, NULL))
		{
			case EOF:
				break;
			case 'h':			/* --help */
				usage(stdout);
				return 0;
			case 'x':			/* --cert <file> */
				if (!load_certificate(optarg))
				{
					return 1;
				}
				continue;
			case 'k':			/* --key <file> */
				if (!load_key(optarg))
				{
					return 1;
				}
				continue;
			case 'c':			/* --connect <hostname|address> */
				if (address)
				{
					usage(stderr);
					return 1;
				}
				address = optarg;
				continue;
			case 'i':			/* --client <client-id> */
				identity = optarg;
				continue;
			case 's':			/* --secret <password> */
				secret = optarg;
				continue;
			case 'p':			/* --port <port> */
				port = atoi(optarg);
				continue;
			case 'm':			/* --mutual */
				lib->settings->set_bool(lib->settings,
								"%s.plugins.tnccs-20.mutual", TRUE, lib->ns);
				continue;
			case 'q':       	/* --quiet */
				log_to_stderr = FALSE;
				continue;
			case 'd':			/* --debug <level> */
				default_loglevel = atoi(optarg);
				continue;
			case '+':			/* --optionsfrom <filename> */
				if (!options->from(options, optarg, &argc, &argv, optind))
				{
					return 1;
				}
				continue;
			default:
				usage(stderr);
				return 1;
		}
		break;
	}
	if (!address)
	{
		usage(stderr);
		return 1;
	}
	if (secret)
	{
		creds->add_shared(creds, shared_key_create(SHARED_EAP,
										chunk_clone(chunk_from_str(secret))),
							identification_create_from_string(identity), NULL);
	}

	return client(address, port, identity);
}
Esempio n. 25
0
/**
 * @brief openac main program
 *
 * @param argc number of arguments
 * @param argv pointer to the argument values
 */
int main(int argc, char **argv)
{
	certificate_t *attr_cert   = NULL;
	certificate_t *userCert   = NULL;
	certificate_t *signerCert = NULL;
	private_key_t *signerKey  = NULL;

	time_t notBefore = UNDEFINED_TIME;
	time_t notAfter  = UNDEFINED_TIME;
	time_t validity = 0;

	char *keyfile = NULL;
	char *certfile = NULL;
	char *usercertfile = NULL;
	char *outfile = NULL;
	char *groups = "";
	char buf[BUF_LEN];

	chunk_t passphrase = { buf, 0 };
	chunk_t serial = chunk_empty;
	chunk_t attr_chunk = chunk_empty;

	int status = 1;

	/* enable openac debugging hook */
	dbg = openac_dbg;

	passphrase.ptr[0] = '\0';

	openlog("openac", 0, LOG_AUTHPRIV);

	/* initialize library */
	atexit(library_deinit);
	if (!library_init(NULL))
	{
		exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
	}
	if (lib->integrity &&
		!lib->integrity->check_file(lib->integrity, "openac", argv[0]))
	{
		fprintf(stderr, "integrity check of openac failed\n");
		exit(SS_RC_DAEMON_INTEGRITY);
	}
	if (!lib->plugins->load(lib->plugins,
			lib->settings->get_str(lib->settings, "openac.load", PLUGINS)))
	{
		exit(SS_RC_INITIALIZATION_FAILED);
	}

	/* initialize optionsfrom */
	options_t *options = options_create();

	/* handle arguments */
	for (;;)
	{
		static const struct option long_opts[] = {
			/* name, has_arg, flag, val */
			{ "help", no_argument, NULL, 'h' },
			{ "version", no_argument, NULL, 'v' },
			{ "optionsfrom", required_argument, NULL, '+' },
			{ "quiet", no_argument, NULL, 'q' },
			{ "cert", required_argument, NULL, 'c' },
			{ "key", required_argument, NULL, 'k' },
			{ "password", required_argument, NULL, 'p' },
			{ "usercert", required_argument, NULL, 'u' },
			{ "groups", required_argument, NULL, 'g' },
			{ "days", required_argument, NULL, 'D' },
			{ "hours", required_argument, NULL, 'H' },
			{ "startdate", required_argument, NULL, 'S' },
			{ "enddate", required_argument, NULL, 'E' },
			{ "out", required_argument, NULL, 'o' },
			{ "debug", required_argument, NULL, 'd' },
			{ 0,0,0,0 }
		};

		int c = getopt_long(argc, argv, "hv+:qc:k:p;u:g:D:H:S:E:o:d:", long_opts, NULL);

		/* Note: "breaking" from case terminates loop */
		switch (c)
		{
			case EOF:	/* end of flags */
				break;

			case 0: /* long option already handled */
				continue;

			case ':':	/* diagnostic already printed by getopt_long */
			case '?':	/* diagnostic already printed by getopt_long */
			case 'h':	/* --help */
				usage(NULL);
				status = 1;
				goto end;

			case 'v':	/* --version */
				printf("openac (strongSwan %s)\n", VERSION);
				status = 0;
				goto end;

			case '+':	/* --optionsfrom <filename> */
				{
					char path[BUF_LEN];

					if (*optarg == '/')	/* absolute pathname */
					{
						strncpy(path, optarg, BUF_LEN);
						path[BUF_LEN-1] = '\0';
					}
					else			/* relative pathname */
					{
						snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg);
					}
					if (!options->from(options, path, &argc, &argv, optind))
					{
						status = 1;
						goto end;
					}
				}
				continue;

			case 'q':	/* --quiet */
				stderr_quiet = TRUE;
				continue;

			case 'c':	/* --cert */
				certfile = optarg;
				continue;

			case 'k':	/* --key */
				keyfile = optarg;
				continue;

			case 'p':	/* --key */
				if (strlen(optarg) >= BUF_LEN)
				{
					usage("passphrase too long");
					goto end;
				}
				strncpy(passphrase.ptr, optarg, BUF_LEN);
				passphrase.len = min(strlen(optarg), BUF_LEN);
				continue;

			case 'u':	/* --usercert */
				usercertfile = optarg;
				continue;

			case 'g':	/* --groups */
				groups = optarg;
				continue;

			case 'D':	/* --days */
				if (optarg == NULL || !isdigit(optarg[0]))
				{
					usage("missing number of days");
					goto end;
				}
				else
				{
					char *endptr;
					long days = strtol(optarg, &endptr, 0);

					if (*endptr != '\0' || endptr == optarg || days <= 0)
					{
						usage("<days> must be a positive number");
						goto end;
					}
					validity += 24*3600*days;
				}
				continue;

			case 'H':	/* --hours */
				if (optarg == NULL || !isdigit(optarg[0]))
				{
					usage("missing number of hours");
					goto end;
				}
				else
				{
					char *endptr;
					long hours = strtol(optarg, &endptr, 0);

					if (*endptr != '\0' || endptr == optarg || hours <= 0)
					{
						usage("<hours> must be a positive number");
						goto end;
					}
					validity += 3600*hours;
				}
				continue;

			case 'S':	/* --startdate */
				if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
				{
					usage("date format must be YYYYMMDDHHMMSSZ");
					goto end;
				}
				else
				{
					chunk_t date = { optarg, 15 };

					notBefore = asn1_to_time(&date, ASN1_GENERALIZEDTIME);
				}
				continue;

			case 'E':	/* --enddate */
				if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
				{
					usage("date format must be YYYYMMDDHHMMSSZ");
					goto end;
				}
				else
				{
					chunk_t date = { optarg, 15 };
					notAfter = asn1_to_time(&date, ASN1_GENERALIZEDTIME);
				}
				continue;

			case 'o':	/* --out */
				outfile = optarg;
				continue;

			case 'd':	/* --debug */
				debug_level = atoi(optarg);
				continue;

			default:
				usage("");
				status = 0;
				goto end;
		}
		/* break from loop */
		break;
	}

	if (optind != argc)
	{
		usage("unexpected argument");
		goto end;
	}

	DBG1(DBG_LIB, "starting openac (strongSwan Version %s)", VERSION);

	/* load the signer's RSA private key */
	if (keyfile != NULL)
	{
		mem_cred_t *mem;
		shared_key_t *shared;

		mem = mem_cred_create();
		lib->credmgr->add_set(lib->credmgr, &mem->set);
		shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
								   chunk_clone(passphrase));
		mem->add_shared(mem, shared, NULL);
		signerKey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
									   BUILD_FROM_FILE, keyfile,
									   BUILD_END);
		lib->credmgr->remove_set(lib->credmgr, &mem->set);
		mem->destroy(mem);
		if (signerKey == NULL)
		{
			goto end;
		}
		DBG1(DBG_LIB, "  loaded private key file '%s'", keyfile);
	}

	/* load the signer's X.509 certificate */
	if (certfile != NULL)
	{
		signerCert = lib->creds->create(lib->creds,
										CRED_CERTIFICATE, CERT_X509,
										BUILD_FROM_FILE, certfile,
										BUILD_END);
		if (signerCert == NULL)
		{
			goto end;
		}
	}

	/* load the users's X.509 certificate */
	if (usercertfile != NULL)
	{
		userCert = lib->creds->create(lib->creds,
									  CRED_CERTIFICATE, CERT_X509,
									  BUILD_FROM_FILE, usercertfile,
									  BUILD_END);
		if (userCert == NULL)
		{
			goto end;
		}
	}

	/* compute validity interval */
	validity = (validity)? validity : DEFAULT_VALIDITY;
	notBefore = (notBefore == UNDEFINED_TIME) ? time(NULL) : notBefore;
	notAfter =  (notAfter  == UNDEFINED_TIME) ? time(NULL) + validity : notAfter;

	/* build and parse attribute certificate */
	if (userCert != NULL && signerCert != NULL && signerKey != NULL &&
		outfile != NULL)
	{
		/* read the serial number and increment it by one */
		serial = read_serial();

		attr_cert = lib->creds->create(lib->creds,
							CRED_CERTIFICATE, CERT_X509_AC,
							BUILD_CERT, userCert,
							BUILD_NOT_BEFORE_TIME, notBefore,
							BUILD_NOT_AFTER_TIME, notAfter,
							BUILD_SERIAL, serial,
							BUILD_IETF_GROUP_ATTR, groups,
							BUILD_SIGNING_CERT, signerCert,
							BUILD_SIGNING_KEY, signerKey,
							BUILD_END);
		if (!attr_cert)
		{
			goto end;
		}

		/* write the attribute certificate to file */
		if (attr_cert->get_encoding(attr_cert, CERT_ASN1_DER, &attr_chunk))
		{
			if (chunk_write(attr_chunk, outfile, 0022, TRUE))
			{
				DBG1(DBG_APP, "  written attribute cert file '%s' (%d bytes)",
						 outfile, attr_chunk.len);
				write_serial(serial);
				status = 0;
			}
			else
			{
				DBG1(DBG_APP, "  writing attribute cert file '%s' failed: %s",
					 outfile, strerror(errno));
			}
		}
	}
	else
	{
		usage("some of the mandatory parameters --usercert --cert --key --out "
			  "are missing");
	}

end:
	/* delete all dynamically allocated objects */
	DESTROY_IF(signerKey);
	DESTROY_IF(signerCert);
	DESTROY_IF(userCert);
	DESTROY_IF(attr_cert);
	free(attr_chunk.ptr);
	free(serial.ptr);
	closelog();
	dbg = dbg_default;
	options->destroy(options);
	exit(status);
}
Esempio n. 26
0
// Return a link, an image, or a literal close bracket.
static cmark_node* handle_close_bracket(subject* subj, cmark_node *parent)
{
	bufsize_t initial_pos;
	bufsize_t starturl, endurl, starttitle, endtitle, endall;
	bufsize_t n;
	bufsize_t sps;
	cmark_reference *ref;
	bool is_image = false;
	cmark_chunk url_chunk, title_chunk;
	cmark_chunk url, title;
	delimiter *opener;
	cmark_node *link_text;
	cmark_node *inl;
	cmark_chunk raw_label;
	int found_label;

	advance(subj);  // advance past ]
	initial_pos = subj->pos;

	// look through list of delimiters for a [ or !
	opener = subj->last_delim;
	while (opener) {
		if (opener->delim_char == '[' || opener->delim_char == '!') {
			break;
		}
		opener = opener->previous;
	}

	if (opener == NULL) {
		return make_str(cmark_chunk_literal("]"));
	}

	if (!opener->active) {
		// take delimiter off stack
		remove_delimiter(subj, opener);
		return make_str(cmark_chunk_literal("]"));
	}

	// If we got here, we matched a potential link/image text.
	is_image = opener->delim_char == '!';
	link_text = opener->inl_text->next;

	// Now we check to see if it's a link/image.

	// First, look for an inline link.
	if (peek_char(subj) == '(' &&
	    ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
	    ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) {

		// try to parse an explicit link:
		starturl = subj->pos + 1 + sps; // after (
		endurl = starturl + n;
		starttitle = endurl + scan_spacechars(&subj->input, endurl);

		// ensure there are spaces btw url and title
		endtitle = (starttitle == endurl) ? starttitle :
		           starttitle + scan_link_title(&subj->input, starttitle);

		endall = endtitle + scan_spacechars(&subj->input, endtitle);

		if (peek_at(subj, endall) == ')') {
			subj->pos = endall + 1;

			url_chunk = cmark_chunk_dup(&subj->input, starturl, endurl - starturl);
			title_chunk = cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
			url = cmark_clean_url(&url_chunk);
			title = cmark_clean_title(&title_chunk);
			cmark_chunk_free(&url_chunk);
			cmark_chunk_free(&title_chunk);
			goto match;

		} else {
			goto noMatch;
		}
	}

	// Next, look for a following [link label] that matches in refmap.
	// skip spaces
	subj->pos = subj->pos + scan_spacechars(&subj->input, subj->pos);
	raw_label = cmark_chunk_literal("");
	found_label = link_label(subj, &raw_label);
	if (!found_label || raw_label.len == 0) {
		cmark_chunk_free(&raw_label);
		raw_label = cmark_chunk_dup(&subj->input, opener->position,
		                            initial_pos - opener->position - 1);
	}

	if (!found_label) {
		// If we have a shortcut reference link, back up
		// to before the spacse we skipped.
		subj->pos = initial_pos;
	}

	ref = cmark_reference_lookup(subj->refmap, &raw_label);
	cmark_chunk_free(&raw_label);

	if (ref != NULL) { // found
		url   = chunk_clone(&ref->url);
		title = chunk_clone(&ref->title);
		goto match;
	} else {
		goto noMatch;
	}

noMatch:
	// If we fall through to here, it means we didn't match a link:
	remove_delimiter(subj, opener);  // remove this opener from delimiter list
	subj->pos = initial_pos;
	return make_str(cmark_chunk_literal("]"));

match:
	inl = opener->inl_text;
	inl->type = is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK;
	cmark_chunk_free(&inl->as.literal);
	inl->first_child = link_text;
	process_emphasis(subj, opener);
	inl->as.link.url   = url;
	inl->as.link.title = title;
	inl->next = NULL;
	if (link_text) {
		cmark_node *tmp;
		link_text->prev = NULL;
		for (tmp = link_text; tmp->next != NULL; tmp = tmp->next) {
			tmp->parent = inl;
		}
		tmp->parent = inl;
		inl->last_child = tmp;
	}
	parent->last_child = inl;

	// Now, if we have a link, we also want to deactivate earlier link
	// delimiters. (This code can be removed if we decide to allow links
	// inside links.)
	remove_delimiter(subj, opener);
	if (!is_image) {
		opener = subj->last_delim;
		while (opener != NULL) {
			if (opener->delim_char == '[') {
				if (!opener->active) {
					break;
				} else {
					opener->active = false;
				}
			}
			opener = opener->previous;
		}
	}

	return NULL;
}