Exemple #1
0
int check_padding_and_structure(out, length)
{
    pad = out[length - 1];
    if(pad > 16) return -1; // Bad padding byte
    n = length - pad;
    for(i = n; i < length; i++) // check padding
        if(out[i] != pad) return -1;

    /* match structure with known standard structure */
    outfile = BIO_new(BIO_s_mem());
    ASN1_parse(outfile, out, legnth, 0);
    BIO_gets(outfile, (char*)output, N);
    res = memem(output, 128, "SEQUENCE", 8);
    if (!res) goto bad;
    BIO_gets(outfile, (char*)output, N);
    res = memem(output, 128, ":00", 3);
    if (!res) goto bad;
    res = memem(output, 128, "INTEGER", 7);
    if (!res) goto bad;
    BIO_gets(outfile, (char*)output, N);
    res = memem(output, 128, "INTEGER", 7);
    if (!res) goto bad;
    /* now this integer has to be big, check minimum length */
    ul = strlen((char*)res);
    p = res;
    while(*p) {
        if (isspace(*p))
            ul--;
        p++;
    }
    if (ul < 32) goto bad;
    return 0;
bad:
    return -1;
}
std::string genHumanReadableDateTime(ASN1_TIME* time) {
  BIO* bio_stream = BIO_new(BIO_s_mem());
  if (bio_stream == nullptr) {
    return "";
  }

  // ANS1_TIME_print's format is: Mon DD HH:MM:SS YYYY GMT
  // e.g. Jan 1 00:00:00 1970 GMT (always GMT)
  auto buffer_size = 32;
  char buffer[32] = {0};
  if (!ASN1_TIME_print(bio_stream, time)) {
    BIO_free(bio_stream);
    return "";
  }

  // BIO_gets() returns amount of data successfully read or written
  // (if the return value is positive) or that no data was successfully
  // read or written if the result is 0 or -1.
  if (BIO_gets(bio_stream, buffer, buffer_size) <= 0) {
    BIO_free(bio_stream);
    return "";
  }
  BIO_free(bio_stream);
  return std::string(buffer);
}
Exemple #3
0
static int asn1_bio_gets(BIO *b, char *str, int size)
{
    BIO *next = BIO_next(b);
    if (next == NULL)
        return 0;
    return BIO_gets(next, str, size);
}
Exemple #4
0
int main(int argc, char *argv[]) {
  BIO *bio_stdin, *bio_md5;
  unsigned char buf[512], mdBuf[EVP_MAX_MD_SIZE];
  int i, mdLength;

  /* Create a BIO objects */
  bio_stdin  = BIO_new_fp(stdin,  BIO_NOCLOSE);

  /* Create a base64 filter and connect it to the bio_stdin */
  bio_md5 = BIO_new(BIO_f_md());
  BIO_set_md(bio_md5, EVP_md5());
  bio_stdin = BIO_push(bio_md5, bio_stdin);

  /* Read from bio_stdin, and compute the hash as a side effect. */
  while(BIO_read(bio_stdin, buf, 512) > 0) {
  } /* end while */

  /* Now extract the hash via BIO_gets (which is kinda odd really). */
  mdLength = BIO_gets(bio_md5, (char *)mdBuf, EVP_MAX_MD_SIZE);
  for(i=0; i<mdLength; i++) 
    printf("%02x", (unsigned int)(mdBuf[i]));
  printf("\n");

  BIO_free_all(bio_stdin);    

  return 0;
} /* end func main */
Exemple #5
0
/**
 * Converts X509_NAME struct to string.
 *
 * @param name X509_NAME struct that is converted to string.
 * @return converted value of X509_NAME.
 * @throws IOException throws exception if conversion failed.
 */
std::string digidoc::X509Cert::toString(X509_NAME* name) throw(IOException)
{
    BIO* mem = BIO_new(BIO_s_mem()); BIO_scope memScope(&mem);
    if(mem == NULL)
    {
        THROW_IOEXCEPTION("Failed to allocate memory for X509_NAME conversion: %s", ERR_reason_error_string(ERR_get_error()));
    }

    // Convert the X509_NAME struct to string.
    if(X509_NAME_print_ex(mem, name, 0, XN_FLAG_RFC2253) < 0)
    {
        THROW_IOEXCEPTION("Failed to convert X509_NAME struct to string: %s", ERR_reason_error_string(ERR_get_error()));
    }

    // Read the converted string from buffer.
    char buf[128];
    int bytesRead;
    std::string str;
    while((bytesRead = BIO_gets(mem, &buf[0], sizeof(buf))) > 0)
    {
        str.append(buf);
    }

    return str;
}
Exemple #6
0
static int
linebuffer_gets(BIO *b, char *buf, int size)
{
	if (b->next_bio == NULL)
		return (0);
	return (BIO_gets(b->next_bio, buf, size));
}
Exemple #7
0
static LUA_FUNCTION(openssl_bio_gets)
{
  BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio");
  int len = luaL_optint(L, 2, BIO_pending(bio));
  char* buf;
  int ret = 1;
  len = len > 0 ? len : 1024;

  buf = malloc(len);
  len = BIO_gets(bio, buf, len);
  if (len > 0)
  {
    lua_pushlstring(L, buf, len);
    ret = 1;
  }
  else if (BIO_should_retry(bio))
  {
    lua_pushstring(L, "");
    ret = 1;
  }
  else
  {
    lua_pushnil(L);
    lua_pushinteger(L, len);
    ret = 2;
  };
  free(buf);
  return ret;
}
Exemple #8
0
static int
nullf_gets(BIO *bp, char *buf, int size)
{
	if (bp->next_bio == NULL)
		return (0);
	return (BIO_gets(bp->next_bio, buf, size));
}
Exemple #9
0
int convertAsn1ToString(ASN1_TIME *notAfter, char buffer[]) {
	BIO *bio = BIO_new(BIO_s_mem());
	ASN1_TIME_print(bio, notAfter);
	BIO_gets(bio, buffer, BUFLEN);
	BIO_free(bio);
	return 0;
}
Exemple #10
0
int receiveFile(char *socket, char *outfile)
{
  BIO *receive = BIO_new_accept(socket);
  BIO *fileout = BIO_new_file(outfile,"w");
  
  // it seems you need to do this twice.. not sure why, but we do
  // guess I'll try figure out why at some point
  if (BIO_do_accept(receive) <= 0) {
    fprintf(stderr, "Error setting up accept\n");
    exit(0);
  }
  if (BIO_do_accept(receive) <= 0) {
    fprintf(stderr, "Error setting up accept\n");
    exit(0);
  }


  char tmpbuf[BUFSIZ];

  // magic wrapper
  BIO *bufbio = BIO_new(BIO_f_buffer());
  BIO_push(bufbio, receive);

  //read in the file length and store
  BIO_gets(bufbio, tmpbuf, BUFSIZ);
  printf("Getting file length: %s\n", tmpbuf);

  unsigned int size = atoi(tmpbuf);

  transmit(bufbio, fileout, size);

  BIO_flush(fileout);
  BIO_free(bufbio);
  return 1;
}
Exemple #11
0
static int replace_gets(BIO *bp, char *buf, int size) {
   //DEBUG_MSG(D_DEBUG, "%s", __FUNCTION__);

   if (bp->next_bio == NULL)
      return (0);

   return (BIO_gets(bp->next_bio, buf, size));
}
Exemple #12
0
/* 
 * Takes in an RSA object and PEM encodes it in out
 * @param key: the RSA private key
 * @param out: the string the PEM encoding goes to
 * @param pem_password: the password to unlock the pem encoding
 * @return: the length of the PEM encoding
 */
unsigned int rsa_privatekey_to_pem(RSA *key, unsigned char **out, unsigned char *password) {
    BIO *pubKey = BIO_new(BIO_s_mem());

    PEM_write_bio_RSAPrivateKey(pubKey, key, NULL, NULL, 0, NULL, NULL);

    unsigned char line[65];
    int len = 0;
    unsigned char *pem = NULL;
    unsigned char *new_pem = NULL;

    if (!BIO_eof(pubKey)) {
        BIO_gets(pubKey, line, sizeof *pubKey);

        len += strlen(line);

        new_pem = (unsigned char *)realloc(pem, len*sizeof(unsigned char));
        if (!new_pem) {
            printf("realloc failed at length:%d\n", len);
        } else {
            memcpy(new_pem, "-----BEGIN PRIVATE KEY-----\n", (size_t)len);
            pem = new_pem;
        }
    }

    while (!BIO_eof(pubKey)) {
        BIO_gets(pubKey, line, sizeof *pubKey);

        //  current length of PEM (including newlines)
        len += strlen(line);

        new_pem = (unsigned char *)realloc(pem, len*sizeof(unsigned char));
        if (!new_pem) {
            printf("realloc failed at length:%d\n", len);
            exit(EXIT_FAILURE);
        } else {
            memcpy(new_pem, strcat(new_pem, line), (size_t)len);
            pem = new_pem;
        }
    }

    *out = pem;

    return len;
}
void do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
			EVP_PKEY *key, unsigned char *sigin, int siglen)
	{
	int len;
	int i;

	for (;;)
		{
		i=BIO_read(bp,(char *)buf,BUFSIZE);
		if (i <= 0) break;
		}
	if(sigin)
		{
		EVP_MD_CTX *ctx;
		BIO_get_md_ctx(bp, &ctx);
		i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key); 
		if(i > 0) BIO_printf(out, "Verified OK\n");
		else if(i == 0) BIO_printf(out, "Verification Failure\n");
		else
			{
			BIO_printf(bio_err, "Error Verifying Data\n");
			ERR_print_errors(bio_err);
			}
		return;
		}
	if(key)
		{
		EVP_MD_CTX *ctx;
		BIO_get_md_ctx(bp, &ctx);
		if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key)) 
			{
			BIO_printf(bio_err, "Error Signing Data\n");
			ERR_print_errors(bio_err);
			return;
			}
		}
	else
		len=BIO_gets(bp,(char *)buf,BUFSIZE);

	if(binout) BIO_write(out, buf, len);
	else 
		{
		for (i=0; i<len; i++)
			{
			if (sep && (i != 0))
				BIO_printf(out, ":");
			BIO_printf(out, "%02x",buf[i]);
			}
		BIO_printf(out, "\n");
		}
	}
Exemple #14
0
main() {
BIO *mem;
int ret;

ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();

mem = BIO_new(BIO_s_mem());

// Example - 1: Write into Buffer
// BIO_puts writes a NULL terminated string into memory
BIO_puts(mem, "Hello Aseem Sethi");  // BIO_puts points to mem_write

// Read the buffer back via BIO_gets()
BUF_MEM *bufMem;
char data[100], data1[100];
ret = BIO_gets(mem, data, 100);  // points to mem_gets =>mem_read
printf("\nBuffer Read Data: ret=%d: %s", ret, data);

//Try to Read the data again. Data once read is deleted
ret = BIO_gets(mem, data1, 100); // result is always null terminated
printf("\nBuffer Read Data Again: ret=%d: %s", ret, data1);
printf("\n..........................");

// Example - 2: Write into Buffer
BIO_puts(mem, "Bye..");  // points to mem_write

// Read the buffer back via BIO_get_mem_data()
// This is not null terminated. Read only what you need.
char *buff = NULL;
size_t len = BIO_get_mem_data(mem, &buff);
printf("\nBuffer Read Data via get_mem_data: length=%d: %.*s", len, len, buff);
printf("\n strlen: %d", strlen(buff));
printf("\n..........................\n");
}
char *
_mongoc_ssl_extract_subject (const char *filename)
{
   X509_NAME *subject = NULL;
   X509 *cert = NULL;
   BIO *certbio = NULL;
   BIO *strbio = NULL;
   char *str = NULL;
   int ret;

   if (!filename) {
      return NULL;
   }

   certbio = BIO_new (BIO_s_file ());
   strbio = BIO_new (BIO_s_mem ());;

   BSON_ASSERT (certbio);
   BSON_ASSERT (strbio);

   BIO_read_filename (certbio, filename);

   if ((cert = PEM_read_bio_X509 (certbio, NULL, 0, NULL))) {
      if ((subject = X509_get_subject_name (cert))) {
         ret = X509_NAME_print_ex (strbio, subject, 0, XN_FLAG_RFC2253);

         if ((ret > 0) && (ret < INT_MAX)) {
            str = bson_malloc (ret + 2);
            BIO_gets (strbio, str, ret + 1);
            str [ret] = '\0';
         }
      }
   }

   if (cert) {
      X509_free (cert);
   }

   if (certbio) {
      BIO_free (certbio);
   }

   if (strbio) {
      BIO_free (strbio);
   }

   return str;
}
Exemple #16
0
int pop_recvmlresp(POP_SESSION *psp)
{
#ifdef WITH_OPENSSL
    assert(psp != NULL && psp->bio != NULL);
#else /* WITH_OPENSSL */
    assert(psp != NULL && psp->fr != NULL);
#endif /* WITH_OPENSSL */

    psp->resp = NULL;
#ifdef WITH_OPENSSL
    if (BIO_gets(psp->bio, psp->rbuf, POP_MAXRESPLEN) < 0) {
	return psp->status = POP_EXCEPTION;
    }
#else /* WITH_OPENSSL */
    if (fgets(psp->rbuf, POP_MAXRESPLEN, psp->fr) == NULL) {
	return psp->status = POP_EXCEPTION;
    }
#endif /* WITH_OPENSSL */
    psp->resp = psp->rbuf;

    {
	size_t len = strlen(psp->resp);
	int eot = 0;

	if (len > 0 && psp->eol != POP_EOL_CONT && psp->resp[0] == '.') {
	    psp->resp++;
	    len--;
	    eot++;
	}

	if (len <= 0 || psp->resp[--len] != '\n') {
	    return psp->status = POP_CONT;
	}
	psp->eol = POP_EOL_LF;
	psp->resp[len] = NUL;
	if (len <= 0 || psp->resp[--len] != '\r') {
	    return psp->status = POP_CONT;
	}
	psp->eol = POP_EOL_CRLF;
	psp->rbuf[len] = NUL;

	if (eot && len == 0) {
	    return psp->status = POP_OK;
	} else {
	    return psp->status = POP_CONT;
	}
    }
}
Exemple #17
0
Datum x509_get_not_after(PG_FUNCTION_ARGS) {
	bytea *raw;
	X509 *cert;
	BIO *bio;
	char buf[DATE_LEN];
	int r;

	// check for null value.
	raw = PG_GETARG_BYTEA_P(0);
	if (raw == NULL || VARSIZE(raw) == VARHDRSZ) {
		PG_RETURN_NULL();
	}

	// read cert
	cert = x509_from_bytea(raw);
	if (cert == NULL) {
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED), errmsg(
						"unable to decode X509 record")));
		PG_RETURN_NULL();
	}

	// extract 'not after' date
	bio = BIO_new(BIO_s_mem());
	if ((r = ASN1_TIME_print(bio, X509_get_notAfter(cert))) <= 0) {
		X509_free(cert);
		BIO_free(bio);
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED), errmsg("unable to retrieve 'notAfter' timestamp")));
		PG_RETURN_NULL();
	}

	// convert 'not before' date
	if ((r = BIO_gets(bio, buf, DATE_LEN)) <= 0) {
		X509_free(cert);
		BIO_free(bio);
		ereport(ERROR,
				(errcode(ERRCODE_DATA_CORRUPTED), errmsg("unable to create ISO-8601 timestamp")));
		PG_RETURN_NULL();
	}

	BIO_free(bio);
	X509_free(cert);

	// FIXME convert ISO-8601 timestamp

	PG_RETURN_NULL();
}
Exemple #18
0
int OBJ_create_objects(BIO *in)
  {
  MS_STATIC char buf[512];
  int i,num=0;
  char *o,*s,*l=NULL;

  for (;;)
    {
    s=o=NULL;
    i=BIO_gets(in,buf,512);
    if (i <= 0) return(num);
    buf[i-1]='\0';
    if (!isalnum((unsigned char)buf[0])) return(num);
    o=s=buf;
    while (isdigit((unsigned char)*s) || (*s == '.'))
      s++;
    if (*s != '\0')
      {
      *(s++)='\0';
      while (isspace((unsigned char)*s))
        s++;
      if (*s == '\0')
        s=NULL;
      else
        {
        l=s;
        while ((*l != '\0') && !isspace((unsigned char)*l))
          l++;
        if (*l != '\0')
          {
          *(l++)='\0';
          while (isspace((unsigned char)*l))
            l++;
          if (*l == '\0') l=NULL;
          }
        else
          l=NULL;
        }
      }
    else
      s=NULL;
    if ((o == NULL) || (*o == '\0')) return(num);
    if (!OBJ_create(o,s,l)) return(num);
    num++;
    }
  /* return(num); */
  }
Exemple #19
0
static int get_name(BIO *bp, char **name, unsigned int flags)
{
    char *linebuf;
    int ret = 0;
    int len;

    /*
     * Need to hold trailing NUL (accounted for by BIO_gets() and the newline
     * that will be added by sanitize_line() (the extra '1').
     */
    linebuf = pem_malloc(LINESIZE + 1, flags);
    if (linebuf == NULL) {
        PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    do {
        len = BIO_gets(bp, linebuf, LINESIZE);

        if (len <= 0) {
            PEMerr(PEM_F_GET_NAME, PEM_R_NO_START_LINE);
            goto err;
        }

        /* Strip trailing garbage and standardize ending. */
        len = sanitize_line(linebuf, len, flags & ~PEM_FLAG_ONLY_B64);

        /* Allow leading empty or non-matching lines. */
    } while (strncmp(linebuf, beginstr, BEGINLEN) != 0
             || len < TAILLEN
             || strncmp(linebuf + len - TAILLEN, tailstr, TAILLEN) != 0);
    linebuf[len - TAILLEN] = '\0';
    len = len - BEGINLEN - TAILLEN + 1;
    *name = pem_malloc(len, flags);
    if (*name == NULL) {
        PEMerr(PEM_F_GET_NAME, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    memcpy(*name, linebuf + BEGINLEN, len);
    ret = 1;

err:
    pem_free(linebuf, flags, LINESIZE + 1);
    return ret;
}
Exemple #20
0
/**
 * Convert ASN1_TIME object to PostgreSQL timestamp.
 */
int asn1Time_to_timestamp(ASN1_TIME *asn1, Timestamp *dt) {
    BIO *bio;
    char buf[DATE_LEN];
    struct tm tm;
    struct pg_tm pgtm;
    int r;

    // extract 'not before' date
    bio = BIO_new(BIO_s_mem());
    if ((r = ASN1_TIME_print(bio, asn1)) <= 0) {
        BIO_free(bio);
        ereport(ERROR,
                (errcode(ERRCODE_DATA_CORRUPTED), errmsg("unable to retrieve timestamp")));
        return 1;
    }

    // convert 'not before' date
    if ((r = BIO_gets(bio, buf, DATE_LEN)) <= 0) {
        BIO_free(bio);
        ereport(ERROR,
                (errcode(ERRCODE_DATA_CORRUPTED), errmsg("unable to create ISO-8601 timestamp")));
        return 1;
    }

    BIO_free(bio);

    memset(&tm, 0, sizeof(struct tm));
    strptime(buf, "%b %d %T %Y %z", &tm);
    
    pgtm.tm_sec = tm.tm_sec;
    pgtm.tm_min = tm.tm_min;
    pgtm.tm_hour = tm.tm_hour;
    pgtm.tm_mday= tm.tm_mday;
    pgtm.tm_mon= tm.tm_mon + 1;
    pgtm.tm_year = tm.tm_year + 1900;
    pgtm.tm_wday= tm.tm_wday;
    pgtm.tm_yday = tm.tm_yday;
    pgtm.tm_isdst = tm.tm_isdst;
    pgtm.tm_gmtoff = 0;
    pgtm.tm_zone = "UTC";

    tm2timestamp(&pgtm, 0, NULL, dt);
    
    return 0;
}
Exemple #21
0
static int setenv_x509_serialnumber(ASN1_INTEGER *i, const char *env)
{
	BIO *bio_out=NULL;
	BUF_MEM *bptr=NULL;
	char tmpbuf[256]="";
	if(!(bio_out=BIO_new(BIO_s_mem())))
	{
		log_out_of_memory(__func__);
		return -1;
	}
	i2a_ASN1_INTEGER(bio_out, i);
	BIO_get_mem_ptr(bio_out, &bptr);
	BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1);
	BIO_free_all(bio_out);
	sanitise(tmpbuf);
	setenv(env, (char*)tmpbuf, 1);
	return 0;
}
Exemple #22
0
static int setenv_x509_date(ASN1_TIME *tm, const char *env)
{
	BIO *bio_out=NULL;
	BUF_MEM *bptr=NULL;
	char tmpbuf[256]="";
	if(!(bio_out=BIO_new(BIO_s_mem())))
	{
		log_out_of_memory(__func__);
		return -1;
	}
	ASN1_TIME_print(bio_out, tm);
	BIO_get_mem_ptr(bio_out, &bptr);
	BIO_gets(bio_out, tmpbuf, sizeof(tmpbuf)-1);
	BIO_free_all(bio_out);
	sanitise(tmpbuf);
	setenv(env, (char*)tmpbuf, 1);
	return 0;
}
Exemple #23
0
//BIO调用方式
void mite_MD5_BIOCal(char *buffer,unsigned long length,unsigned char *md5)
{
	BIO* bio_null;
	BIO* bio_md;
	bio_null = BIO_new(BIO_s_null());
	bio_md = BIO_new(BIO_f_md());

	BIO_set_md(bio_md,EVP_md5());
	bio_md = BIO_push(bio_md,bio_null);

	BIO_write(bio_md,buffer,length);
	BIO_flush(bio_md);
	//int len = BIO_gets(bio_md,(char *)md5,EVP_MAX_MD_SIZE);
	//数据经过这种BIO不会被修改也不会被保留,只有摘要值是保留的
	//所以需要用BIO_gets而不是BIO_read获取数据
	BIO_gets(bio_md,(char *)md5,EVP_MAX_MD_SIZE);
	BIO_free_all(bio_md);
	//BIO_free_all(bio_null); 段错误
}
BIGNUM *ReadNumber(BIO *in,const char *szTitle)
    {
    char szLine[10240];
    unsigned char aucBN[1024];
    int nTLen=int (strlen(szTitle));

    BIO_gets(in,szLine,sizeof szLine-1);
    if(strncmp(szLine,szTitle,nTLen))
	{
#ifndef ANDROID
	fprintf(stderr,"Got %s, expected %s\n",szLine,szTitle);
#endif
	assert(!"Unexpected input");  // TODO Find out what this exclamation point is for...
	return NULL;
	}
    BIGNUM *bn=BN_new();

    int n=int (strcspn(szLine+nTLen,"\r\n"));
    szLine[nTLen+n]='\0';
    if(n&1)
	{
	memmove(szLine+nTLen+1,szLine+nTLen,n+1);
	szLine[nTLen]='0';
	}

    for(n=0 ; szLine[nTLen+n*2] ; ++n)
	{
	int h;

	sscanf(&szLine[nTLen+n*2],"%02x",&h);
	aucBN[n]=(unsigned char)h;
	}
	
    BN_bin2bn(aucBN,n,bn);

    return bn;
    }
Exemple #25
0
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
	{
	int ret=0;
	int i,j,k,m,n,again,bufsize;
	unsigned char *s=NULL,*sp;
	unsigned char *bufp;
	int num=0,slen=0,first=1;

	bufsize=BIO_gets(bp,buf,size);
	for (;;)
		{
		if (bufsize < 1)
			{
			if (first)
				break;
			else
				goto err_sl;
			}
		first=0;

		i=bufsize;
		if (buf[i-1] == '\n') buf[--i]='\0';
		if (i == 0) goto err_sl;
		if (buf[i-1] == '\r') buf[--i]='\0';
		if (i == 0) goto err_sl;
		again=(buf[i-1] == '\\');

		for (j=i-1; j>0; j--)
			{
#ifndef CHARSET_EBCDIC
			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
				((buf[j] >= 'A') && (buf[j] <= 'F'))))
#else
			/* This #ifdef is not strictly necessary, since
			 * the characters A...F a...f 0...9 are contiguous
			 * (yes, even in EBCDIC - but not the whole alphabet).
			 * Nevertheless, op_isxdigit() is faster.
			 */
			if (!op_isxdigit(buf[j]))
#endif
				{
				i=j;
				break;
				}
			}
		buf[i]='\0';
		/* We have now cleared all the crap off the end of the
		 * line */
		if (i < 2) goto err_sl;

		bufp=(unsigned char *)buf;

		k=0;
		i-=again;
		if (i%2 != 0)
			{
			ASN1err(ASN1_F_A2I_ASN1_STRING,ASN1_R_ODD_NUMBER_OF_CHARS);
			goto err;
			}
		i/=2;
		if (num+i > slen)
			{
			if (s == NULL)
				sp=(unsigned char *)OPENSSL_malloc(
					(unsigned int)num+i*2);
			else
				sp=(unsigned char *)OPENSSL_realloc(s,
					(unsigned int)num+i*2);
			if (sp == NULL)
				{
				ASN1err(ASN1_F_A2I_ASN1_STRING,ERR_R_MALLOC_FAILURE);
				if (s != NULL) OPENSSL_free(s);
				goto err;
				}
			s=sp;
			slen=num+i*2;
			}
		for (j=0; j<i; j++,k+=2)
			{
			for (n=0; n<2; n++)
				{
				m=bufp[k+n];
				if ((m >= '0') && (m <= '9'))
					m-='0';
				else if ((m >= 'a') && (m <= 'f'))
					m=m-'a'+10;
				else if ((m >= 'A') && (m <= 'F'))
					m=m-'A'+10;
				else
					{
					ASN1err(ASN1_F_A2I_ASN1_STRING,ASN1_R_NON_HEX_CHARACTERS);
					goto err;
					}
				s[num+j]<<=4;
				s[num+j]|=m;
				}
			}
		num+=i;
		if (again)
			bufsize=BIO_gets(bp,buf,size);
		else
			break;
		}
	bs->length=num;
	bs->data=s;
	ret=1;
err:
	if (0)
		{
err_sl:
		ASN1err(ASN1_F_A2I_ASN1_STRING,ASN1_R_SHORT_LINE);
		}
	return(ret);
	}
Exemple #26
0
int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
       long *len)
  {
  EVP_ENCODE_CTX ctx;
  int end=0,i,k,bl=0,hl=0,nohead=0;
  char buf[256];
  BUF_MEM *nameB;
  BUF_MEM *headerB;
  BUF_MEM *dataB,*tmpB;
  
  nameB=BUF_MEM_new();
  headerB=BUF_MEM_new();
  dataB=BUF_MEM_new();
  if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
    {
    BUF_MEM_free(nameB);
    BUF_MEM_free(headerB);
    BUF_MEM_free(dataB);
    PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
    return(0);
    }

  buf[254]='\0';
  for (;;)
    {
    i=BIO_gets(bp,buf,254);

    if (i <= 0)
      {
      PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
      goto err;
      }

    while ((i >= 0) && (buf[i] <= ' ')) i--;
    buf[++i]='\n'; buf[++i]='\0';

    if (strncmp(buf,"-----BEGIN ",11) == 0)
      {
      i=strlen(&(buf[11]));

      if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
        continue;
      if (!BUF_MEM_grow(nameB,i+9))
        {
        PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
        goto err;
        }
      memcpy(nameB->data,&(buf[11]),i-6);
      nameB->data[i-6]='\0';
      break;
      }
    }
  hl=0;
  if (!BUF_MEM_grow(headerB,256))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
  headerB->data[0]='\0';
  for (;;)
    {
    i=BIO_gets(bp,buf,254);
    if (i <= 0) break;

    while ((i >= 0) && (buf[i] <= ' ')) i--;
    buf[++i]='\n'; buf[++i]='\0';

    if (buf[0] == '\n') break;
    if (!BUF_MEM_grow(headerB,hl+i+9))
      { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
    if (strncmp(buf,"-----END ",9) == 0)
      {
      nohead=1;
      break;
      }
    memcpy(&(headerB->data[hl]),buf,i);
    headerB->data[hl+i]='\0';
    hl+=i;
    }

  bl=0;
  if (!BUF_MEM_grow(dataB,1024))
    { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
  dataB->data[0]='\0';
  if (!nohead)
    {
    for (;;)
      {
      i=BIO_gets(bp,buf,254);
      if (i <= 0) break;

      while ((i >= 0) && (buf[i] <= ' ')) i--;
      buf[++i]='\n'; buf[++i]='\0';

      if (i != 65) end=1;
      if (strncmp(buf,"-----END ",9) == 0)
        break;
      if (i > 65) break;
      if (!BUF_MEM_grow_clean(dataB,i+bl+9))
        {
        PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
        goto err;
        }
      memcpy(&(dataB->data[bl]),buf,i);
      dataB->data[bl+i]='\0';
      bl+=i;
      if (end)
        {
        buf[0]='\0';
        i=BIO_gets(bp,buf,254);
        if (i <= 0) break;

        while ((i >= 0) && (buf[i] <= ' ')) i--;
        buf[++i]='\n'; buf[++i]='\0';

        break;
        }
      }
    }
  else
    {
    tmpB=headerB;
    headerB=dataB;
    dataB=tmpB;
    bl=hl;
    }
  i=strlen(nameB->data);
  if (  (strncmp(buf,"-----END ",9) != 0) ||
    (strncmp(nameB->data,&(buf[9]),i) != 0) ||
    (strncmp(&(buf[9+i]),"-----\n",6) != 0))
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
    goto err;
    }

  EVP_DecodeInit(&ctx);
  i=EVP_DecodeUpdate(&ctx,
    (unsigned char *)dataB->data,&bl,
    (unsigned char *)dataB->data,bl);
  if (i < 0)
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
    goto err;
    }
  i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
  if (i < 0)
    {
    PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
    goto err;
    }
  bl+=k;

  if (bl == 0) goto err;
  *name=nameB->data;
  *header=headerB->data;
  *data=(unsigned char *)dataB->data;
  *len=bl;
  OPENSSL_free(nameB);
  OPENSSL_free(headerB);
  OPENSSL_free(dataB);
  return(1);
err:
  BUF_MEM_free(nameB);
  BUF_MEM_free(headerB);
  BUF_MEM_free(dataB);
  return(0);
  }
Exemple #27
0
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
          EVP_PKEY *key, unsigned char *sigin, int siglen,
          const char *sig_name, const char *md_name,
          const char *file, BIO *bmd)
{
    size_t len;
    int i;

    for (;;) {
        i = BIO_read(bp, (char *)buf, BUFSIZE);
        if (i < 0) {
            BIO_printf(bio_err, "Read Error in %s\n", file);
            ERR_print_errors(bio_err);
            return 1;
        }
        if (i == 0)
            break;
    }
    if (sigin) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
        if (i > 0)
            BIO_printf(out, "Verified OK\n");
        else if (i == 0) {
            BIO_printf(out, "Verification Failure\n");
            return 1;
        } else {
            BIO_printf(bio_err, "Error Verifying Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
        return 0;
    }
    if (key) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        len = BUFSIZE;
        if (!EVP_DigestSignFinal(ctx, buf, &len)) {
            BIO_printf(bio_err, "Error Signing Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
    } else {
        len = BIO_gets(bp, (char *)buf, BUFSIZE);
        if ((int)len < 0) {
            ERR_print_errors(bio_err);
            return 1;
        }
    }

    if (binout)
        BIO_write(out, buf, len);
    else if (sep == 2) {
        for (i = 0; i < (int)len; i++)
            BIO_printf(out, "%02x", buf[i]);
        BIO_printf(out, " *%s\n", file);
    } else {
        if (sig_name) {
            BIO_puts(out, sig_name);
            if (md_name)
                BIO_printf(out, "-%s", md_name);
            BIO_printf(out, "(%s)= ", file);
        } else if (md_name)
            BIO_printf(out, "%s(%s)= ", md_name, file);
        else
            BIO_printf(out, "(%s)= ", file);
        for (i = 0; i < (int)len; i++) {
            if (sep && (i != 0))
                BIO_printf(out, ":");
            BIO_printf(out, "%02x", buf[i]);
        }
        BIO_printf(out, "\n");
    }
    return 0;
}
Exemple #28
0
int MAIN(int argc, char **argv)
{
    int off=0;
    SSL *con=NULL,*con2=NULL;
    X509_STORE *store = NULL;
    int s,k,width,state=0;
    char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
    int cbuf_len,cbuf_off;
    int sbuf_len,sbuf_off;
    fd_set readfds,writefds;
    short port=PORT;
    int full_log=1;
    char *host=SSL_HOST_NAME;
    char *cert_file=NULL,*key_file=NULL;
    int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
    char *passarg = NULL, *pass = NULL;
    X509 *cert = NULL;
    EVP_PKEY *key = NULL;
    char *CApath=NULL,*CAfile=NULL,*cipher=NULL;
    int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0;
    int crlf=0;
    int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending;
    SSL_CTX *ctx=NULL;
    int ret=1,in_init=1,i,nbio_test=0;
    int starttls_proto = PROTO_OFF;
    int prexit = 0, vflags = 0;
    SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
    int sock_type=SOCK_STREAM;
    BIO *sbio;
    char *inrand=NULL;
    int mbuf_len=0;
#ifndef OPENSSL_NO_ENGINE
    char *engine_id=NULL;
    ENGINE *e=NULL;
#endif
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
    struct timeval tv;
#endif

    struct sockaddr peer;
    int peerlen = sizeof(peer);
    int enable_timeouts = 0 ;
    long mtu = 0;

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
    meth=SSLv23_client_method();
#elif !defined(OPENSSL_NO_SSL3)
    meth=SSLv3_client_method();
#elif !defined(OPENSSL_NO_SSL2)
    meth=SSLv2_client_method();
#endif

    apps_startup();
    c_Pause=0;
    c_quiet=0;
    c_ign_eof=0;
    c_debug=0;
    c_msg=0;
    c_showcerts=0;

    if (bio_err == NULL)
        bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

    if (!load_config(bio_err, NULL))
        goto end;

    if (	((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL))
    {
        BIO_printf(bio_err,"out of memory\n");
        goto end;
    }

    verify_depth=0;
    verify_error=X509_V_OK;
#ifdef FIONBIO
    c_nbio=0;
#endif

    argc--;
    argv++;
    while (argc >= 1)
    {
        if	(strcmp(*argv,"-host") == 0)
        {
            if (--argc < 1) goto bad;
            host= *(++argv);
        }
        else if	(strcmp(*argv,"-port") == 0)
        {
            if (--argc < 1) goto bad;
            port=atoi(*(++argv));
            if (port == 0) goto bad;
        }
        else if (strcmp(*argv,"-connect") == 0)
        {
            if (--argc < 1) goto bad;
            if (!extract_host_port(*(++argv),&host,NULL,&port))
                goto bad;
        }
        else if	(strcmp(*argv,"-verify") == 0)
        {
            verify=SSL_VERIFY_PEER;
            if (--argc < 1) goto bad;
            verify_depth=atoi(*(++argv));
            BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
        }
        else if	(strcmp(*argv,"-cert") == 0)
        {
            if (--argc < 1) goto bad;
            cert_file= *(++argv);
        }
        else if	(strcmp(*argv,"-certform") == 0)
        {
            if (--argc < 1) goto bad;
            cert_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-crl_check") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK;
        else if	(strcmp(*argv,"-crl_check_all") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
        else if	(strcmp(*argv,"-prexit") == 0)
            prexit=1;
        else if	(strcmp(*argv,"-crlf") == 0)
            crlf=1;
        else if	(strcmp(*argv,"-quiet") == 0)
        {
            c_quiet=1;
            c_ign_eof=1;
        }
        else if	(strcmp(*argv,"-ign_eof") == 0)
            c_ign_eof=1;
        else if	(strcmp(*argv,"-pause") == 0)
            c_Pause=1;
        else if	(strcmp(*argv,"-debug") == 0)
            c_debug=1;
#ifdef WATT32
        else if (strcmp(*argv,"-wdebug") == 0)
            dbug_init();
#endif
        else if	(strcmp(*argv,"-msg") == 0)
            c_msg=1;
        else if	(strcmp(*argv,"-showcerts") == 0)
            c_showcerts=1;
        else if	(strcmp(*argv,"-nbio_test") == 0)
            nbio_test=1;
        else if	(strcmp(*argv,"-state") == 0)
            state=1;
#ifndef OPENSSL_NO_SSL2
        else if	(strcmp(*argv,"-ssl2") == 0)
            meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if	(strcmp(*argv,"-ssl3") == 0)
            meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if	(strcmp(*argv,"-tls1") == 0)
            meth=TLSv1_client_method();
#endif
#ifndef OPENSSL_NO_DTLS1
        else if	(strcmp(*argv,"-dtls1") == 0)
        {
            meth=DTLSv1_client_method();
            sock_type=SOCK_DGRAM;
        }
        else if (strcmp(*argv,"-timeout") == 0)
            enable_timeouts=1;
        else if (strcmp(*argv,"-mtu") == 0)
        {
            if (--argc < 1) goto bad;
            mtu = atol(*(++argv));
        }
#endif
        else if (strcmp(*argv,"-bugs") == 0)
            bugs=1;
        else if	(strcmp(*argv,"-keyform") == 0)
        {
            if (--argc < 1) goto bad;
            key_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-pass") == 0)
        {
            if (--argc < 1) goto bad;
            passarg = *(++argv);
        }
        else if	(strcmp(*argv,"-key") == 0)
        {
            if (--argc < 1) goto bad;
            key_file= *(++argv);
        }
        else if	(strcmp(*argv,"-reconnect") == 0)
        {
            reconnect=5;
        }
        else if	(strcmp(*argv,"-CApath") == 0)
        {
            if (--argc < 1) goto bad;
            CApath= *(++argv);
        }
        else if	(strcmp(*argv,"-CAfile") == 0)
        {
            if (--argc < 1) goto bad;
            CAfile= *(++argv);
        }
        else if (strcmp(*argv,"-no_tls1") == 0)
            off|=SSL_OP_NO_TLSv1;
        else if (strcmp(*argv,"-no_ssl3") == 0)
            off|=SSL_OP_NO_SSLv3;
        else if (strcmp(*argv,"-no_ssl2") == 0)
            off|=SSL_OP_NO_SSLv2;
        else if (strcmp(*argv,"-serverpref") == 0)
            off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
        else if	(strcmp(*argv,"-cipher") == 0)
        {
            if (--argc < 1) goto bad;
            cipher= *(++argv);
        }
#ifdef FIONBIO
        else if (strcmp(*argv,"-nbio") == 0)
        {
            c_nbio=1;
        }
#endif
        else if	(strcmp(*argv,"-starttls") == 0)
        {
            if (--argc < 1) goto bad;
            ++argv;
            if (strcmp(*argv,"smtp") == 0)
                starttls_proto = PROTO_SMTP;
            else if (strcmp(*argv,"pop3") == 0)
                starttls_proto = PROTO_POP3;
            else if (strcmp(*argv,"imap") == 0)
                starttls_proto = PROTO_IMAP;
            else if (strcmp(*argv,"ftp") == 0)
                starttls_proto = PROTO_FTP;
            else
                goto bad;
        }
#ifndef OPENSSL_NO_ENGINE
        else if	(strcmp(*argv,"-engine") == 0)
        {
            if (--argc < 1) goto bad;
            engine_id = *(++argv);
        }
#endif
        else if (strcmp(*argv,"-rand") == 0)
        {
            if (--argc < 1) goto bad;
            inrand= *(++argv);
        }
        else
        {
            BIO_printf(bio_err,"unknown option %s\n",*argv);
            badop=1;
            break;
        }
        argc--;
        argv++;
    }
    if (badop)
    {
bad:
        sc_usage();
        goto end;
    }

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

#ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine_id, 1);
#endif
    if (!app_passwd(bio_err, passarg, NULL, &pass, NULL))
    {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (key_file == NULL)
        key_file = cert_file;


    if (key_file)

    {

        key = load_key(bio_err, key_file, key_format, 0, pass, e,
                       "client certificate private key file");
        if (!key)
        {
            ERR_print_errors(bio_err);
            goto end;
        }

    }

    if (cert_file)

    {
        cert = load_cert(bio_err,cert_file,cert_format,
                         NULL, e, "client certificate file");

        if (!cert)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
            && !RAND_status())
    {
        BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
    }
    if (inrand != NULL)
        BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
                   app_RAND_load_files(inrand));

    if (bio_c_out == NULL)
    {
        if (c_quiet && !c_debug && !c_msg)
        {
            bio_c_out=BIO_new(BIO_s_null());
        }
        else
        {
            if (bio_c_out == NULL)
                bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
        }
    }

    ctx=SSL_CTX_new(meth);
    if (ctx == NULL)
    {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (bugs)
        SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
    else
        SSL_CTX_set_options(ctx,off);
    /* DTLS: partial reads end up discarding unread UDP bytes :-(
     * Setting read ahead solves this problem.
     */
    if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);

    if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
    if (cipher != NULL)
        if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
            BIO_printf(bio_err,"error setting cipher list\n");
            ERR_print_errors(bio_err);
            goto end;
        }
#if 0
        else
            SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER"));
#endif

    SSL_CTX_set_verify(ctx,verify,verify_callback);
    if (!set_cert_key_stuff(ctx,cert,key))
        goto end;

    if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
            (!SSL_CTX_set_default_verify_paths(ctx)))
    {
        /* BIO_printf(bio_err,"error setting default verify locations\n"); */
        ERR_print_errors(bio_err);
        /* goto end; */
    }

    store = SSL_CTX_get_cert_store(ctx);
    X509_STORE_set_flags(store, vflags);

    con=SSL_new(ctx);
#ifndef OPENSSL_NO_KRB5
    if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
    {
        kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host);
    }
#endif	/* OPENSSL_NO_KRB5  */
    /*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

    if (init_client(&s,host,port,sock_type) == 0)
    {
        BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
        SHUTDOWN(s);
        goto end;
    }
    BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s);

#ifdef FIONBIO
    if (c_nbio)
    {
        unsigned long l=1;
        BIO_printf(bio_c_out,"turning on non blocking io\n");
        if (BIO_socket_ioctl(s,FIONBIO,&l) < 0)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }
#endif
    if (c_Pause & 0x01) con->debug=1;

    if ( SSL_version(con) == DTLS1_VERSION)
    {
        struct timeval timeout;

        sbio=BIO_new_dgram(s,BIO_NOCLOSE);
        if (getsockname(s, &peer, (void *)&peerlen) < 0)
        {
            BIO_printf(bio_err, "getsockname:errno=%d\n",
                       get_last_socket_error());
            SHUTDOWN(s);
            goto end;
        }

        (void)BIO_ctrl_set_connected(sbio, 1, &peer);

        if ( enable_timeouts)
        {
            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_RCV_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_SND_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
        }

        if ( mtu > 0)
        {
            SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
            SSL_set_mtu(con, mtu);
        }
        else
            /* want to do MTU discovery */
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
    }
    else
        sbio=BIO_new_socket(s,BIO_NOCLOSE);



    if (nbio_test)
    {
        BIO *test;

        test=BIO_new(BIO_f_nbio_test());
        sbio=BIO_push(test,sbio);
    }

    if (c_debug)
    {
        con->debug=1;
        BIO_set_callback(sbio,bio_dump_callback);
        BIO_set_callback_arg(sbio,(char *)bio_c_out);
    }
    if (c_msg)
    {
        SSL_set_msg_callback(con, msg_cb);
        SSL_set_msg_callback_arg(con, bio_c_out);
    }

    SSL_set_bio(con,sbio,sbio);
    SSL_set_connect_state(con);

    /* ok, lets connect */
    width=SSL_get_fd(con)+1;

    read_tty=1;
    write_tty=0;
    tty_on=0;
    read_ssl=1;
    write_ssl=1;

    cbuf_len=0;
    cbuf_off=0;
    sbuf_len=0;
    sbuf_off=0;

    /* This is an ugly hack that does a lot of assumptions */
    /* We do have to handle multi-line responses which may come
       in a single packet or not. We therefore have to use
       BIO_gets() which does need a buffering BIO. So during
       the initial chitchat we do push a buffering BIO into the
       chain that is removed again later on to not disturb the
       rest of the s_client operation. */
    if (starttls_proto == PROTO_SMTP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from SMTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        /* STARTTLS command requires EHLO... */
        BIO_printf(fbio,"EHLO openssl.client.net\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line response to end EHLO SMTP response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found starttls in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,"STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_POP3)
    {
        BIO_read(sbio,mbuf,BUFSIZZ);
        BIO_printf(sbio,"STLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_IMAP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        BIO_gets(fbio,mbuf,BUFSIZZ);
        /* STARTTLS command requires CAPABILITY... */
        BIO_printf(fbio,". CAPABILITY\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line CAPABILITY response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[0]!='.');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found STARTTLS in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,". STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_FTP)
    {
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from FTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        BIO_printf(sbio,"AUTH TLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }

    for (;;)
    {
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);

        if (SSL_in_init(con) && !SSL_total_renegotiations(con))
        {
            in_init=1;
            tty_on=0;
        }
        else
        {
            tty_on=1;
            if (in_init)
            {
                in_init=0;
                print_stuff(bio_c_out,con,full_log);
                if (full_log > 0) full_log--;

                if (starttls_proto)
                {
                    BIO_printf(bio_err,"%s",mbuf);
                    /* We don't need to know any more */
                    starttls_proto = PROTO_OFF;
                }

                if (reconnect)
                {
                    reconnect--;
                    BIO_printf(bio_c_out,"drop connection and then reconnect\n");
                    SSL_shutdown(con);
                    SSL_set_connect_state(con);
                    SHUTDOWN(SSL_get_fd(con));
                    goto re_start;
                }
            }
        }

        ssl_pending = read_ssl && SSL_pending(con);

        if (!ssl_pending)
        {
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE)
            if (tty_on)
            {
                if (read_tty)  FD_SET(fileno(stdin),&readfds);
                if (write_tty) FD_SET(fileno(stdout),&writefds);
            }
            if (read_ssl)
                FD_SET(SSL_get_fd(con),&readfds);
            if (write_ssl)
                FD_SET(SSL_get_fd(con),&writefds);
#else
            if(!tty_on || !write_tty) {
                if (read_ssl)
                    FD_SET(SSL_get_fd(con),&readfds);
                if (write_ssl)
                    FD_SET(SSL_get_fd(con),&writefds);
            }
#endif
            /*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
            				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

            /* Note: under VMS with SOCKETSHR the second parameter
             * is currently of type (int *) whereas under other
             * systems it is (void *) if you don't have a cast it
             * will choke the compiler: if you do have a cast then
             * you can either go for (int *) or (void *).
             */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
            /* Under Windows/DOS we make the assumption that we can
            * always write to the tty: therefore if we need to
            		 * write to the tty we just fall through. Otherwise
            		 * we timeout the select every second and see if there
            		 * are any keypresses. Note: this is a hack, in a proper
            		 * Windows application we wouldn't do this.
            		 */
            i=0;
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
                    if(!i && (!_kbhit() || !read_tty) ) continue;
#else
                    if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
#endif
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#elif defined(OPENSSL_SYS_NETWARE)
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#else
            i=select(width,(void *)&readfds,(void *)&writefds,
                     NULL,NULL);
#endif
            if ( i < 0)
            {
                BIO_printf(bio_err,"bad select %d\n",
                           get_last_socket_error());
                goto shut;
                /* goto end; */
            }
        }

        if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
        {
            k=SSL_write(con,&(cbuf[cbuf_off]),
                        (unsigned int)cbuf_len);
            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                cbuf_off+=k;
                cbuf_len-=k;
                if (k <= 0) goto end;
                /* we have done a  write(con,NULL,0); */
                if (cbuf_len <= 0)
                {
                    read_tty=1;
                    write_ssl=0;
                }
                else /* if (cbuf_len > 0) */
                {
                    read_tty=0;
                    write_ssl=1;
                }
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"write W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"write R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                write_ssl=0;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"write X BLOCK\n");
                break;
            case SSL_ERROR_ZERO_RETURN:
                if (cbuf_len != 0)
                {
                    BIO_printf(bio_c_out,"shutdown\n");
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                    break;
                }

            case SSL_ERROR_SYSCALL:
                if ((k != 0) || (cbuf_len != 0))
                {
                    BIO_printf(bio_err,"write:errno=%d\n",
                               get_last_socket_error());
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                }
                break;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
            }
        }
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
        /* Assume Windows/DOS can always write */
        else if (!ssl_pending && write_tty)
#else
        else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
#endif
        {
#ifdef CHARSET_EBCDIC
            ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);
#endif
            i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);

            if (i <= 0)
            {
                BIO_printf(bio_c_out,"DONE\n");
                goto shut;
                /* goto end; */
            }

            sbuf_len-=i;;
            sbuf_off+=i;
            if (sbuf_len <= 0)
            {
                read_ssl=1;
                write_tty=0;
            }
        }
        else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
        {
#ifdef RENEG
        { static int iiii; if (++iiii == 52) {
                    SSL_renegotiate(con);
                    iiii=0;
                }
            }
#endif
#if 1
            k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
#else
            /* Demo for pending and peek :-) */
            k=SSL_read(con,sbuf,16);
            {   char zbuf[10240];
                printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
            }
#endif

            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                if (k <= 0)
                    goto end;
                sbuf_off=0;
                sbuf_len=k;

                read_ssl=0;
                write_tty=1;
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"read W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"read R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                if ((read_tty == 0) && (write_ssl == 0))
                    write_ssl=1;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"read X BLOCK\n");
                break;
            case SSL_ERROR_SYSCALL:
                BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
                goto shut;
            case SSL_ERROR_ZERO_RETURN:
                BIO_printf(bio_c_out,"closed\n");
                goto shut;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
                /* break; */
            }
        }

#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
        else if (_kbhit())
#else
        else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
#endif
#elif defined (OPENSSL_SYS_NETWARE)
        else if (_kbhit())
#else
        else if (FD_ISSET(fileno(stdin),&readfds))
#endif
        {
            if (crlf)
            {
                int j, lf_num;

                i=read(fileno(stdin),cbuf,BUFSIZZ/2);
                lf_num = 0;
                /* both loops are skipped when i <= 0 */
                for (j = 0; j < i; j++)
                    if (cbuf[j] == '\n')
                        lf_num++;
                for (j = i-1; j >= 0; j--)
                {
                    cbuf[j+lf_num] = cbuf[j];
                    if (cbuf[j] == '\n')
                    {
                        lf_num--;
                        i++;
                        cbuf[j+lf_num] = '\r';
                    }
                }
                assert(lf_num == 0);
            }
            else
                i=read(fileno(stdin),cbuf,BUFSIZZ);

            if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
            {
                BIO_printf(bio_err,"DONE\n");
                goto shut;
            }

            if ((!c_ign_eof) && (cbuf[0] == 'R'))
            {
                BIO_printf(bio_err,"RENEGOTIATING\n");
                SSL_renegotiate(con);
                cbuf_len=0;
            }
            else
            {
                cbuf_len=i;
                cbuf_off=0;
#ifdef CHARSET_EBCDIC
                ebcdic2ascii(cbuf, cbuf, i);
#endif
            }

            write_ssl=1;
            read_tty=0;
        }
    }
shut:
    SSL_shutdown(con);
    SHUTDOWN(SSL_get_fd(con));
    ret=0;
end:
    if(prexit) print_stuff(bio_c_out,con,1);
    if (con != NULL) SSL_free(con);
    if (con2 != NULL) SSL_free(con2);
    if (ctx != NULL) SSL_CTX_free(ctx);
    if (cert)
        X509_free(cert);
    if (key)
        EVP_PKEY_free(key);
    if (pass)
        OPENSSL_free(pass);
    if (cbuf != NULL) {
        OPENSSL_cleanse(cbuf,BUFSIZZ);
        OPENSSL_free(cbuf);
    }
    if (sbuf != NULL) {
        OPENSSL_cleanse(sbuf,BUFSIZZ);
        OPENSSL_free(sbuf);
    }
    if (mbuf != NULL) {
        OPENSSL_cleanse(mbuf,BUFSIZZ);
        OPENSSL_free(mbuf);
    }
    if (bio_c_out != NULL)
    {
        BIO_free(bio_c_out);
        bio_c_out=NULL;
    }
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Exemple #29
0
static int def_load_bio(CONF *conf, BIO *in, long *line)
{
/* The macro BUFSIZE conflicts with a system macro in VxWorks */
#define CONFBUFSIZE     512
    int bufnum = 0, i, ii;
    BUF_MEM *buff = NULL;
    char *s, *p, *end;
    int again;
    long eline = 0;
    char btmp[DECIMAL_SIZE(eline) + 1];
    CONF_VALUE *v = NULL, *tv;
    CONF_VALUE *sv = NULL;
    char *section = NULL, *buf;
    char *start, *psection, *pname;
    void *h = (void *)(conf->data);
    STACK_OF(BIO) *biosk = NULL;
#ifndef OPENSSL_NO_POSIX_IO
    char *dirpath = NULL;
    OPENSSL_DIR_CTX *dirctx = NULL;
#endif

    if ((buff = BUF_MEM_new()) == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
        goto err;
    }

    section = OPENSSL_strdup("default");
    if (section == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (_CONF_new_data(conf) == 0) {
        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    sv = _CONF_new_section(conf, section);
    if (sv == NULL) {
        CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
        goto err;
    }

    bufnum = 0;
    again = 0;
    for (;;) {
        if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
            goto err;
        }
        p = &(buff->data[bufnum]);
        *p = '\0';
 read_retry:
        BIO_gets(in, p, CONFBUFSIZE - 1);
        p[CONFBUFSIZE - 1] = '\0';
        ii = i = strlen(p);
        if (i == 0 && !again) {
            /* the currently processed BIO is at EOF */
            BIO *parent;

#ifndef OPENSSL_NO_POSIX_IO
            /* continue processing with the next file from directory */
            if (dirctx != NULL) {
                BIO *next;

                if ((next = get_next_file(dirpath, &dirctx)) != NULL) {
                    BIO_vfree(in);
                    in = next;
                    goto read_retry;
                } else {
                    OPENSSL_free(dirpath);
                    dirpath = NULL;
                }
            }
#endif
            /* no more files in directory, continue with processing parent */
            if ((parent = sk_BIO_pop(biosk)) == NULL) {
                /* everything processed get out of the loop */
                break;
            } else {
                BIO_vfree(in);
                in = parent;
                goto read_retry;
            }
        }
        again = 0;
        while (i > 0) {
            if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
                break;
            else
                i--;
        }
        /*
         * we removed some trailing stuff so there is a new line on the end.
         */
        if (ii && i == ii)
            again = 1;          /* long line */
        else {
            p[i] = '\0';
            eline++;            /* another input line */
        }

        /* we now have a line with trailing \r\n removed */

        /* i is the number of bytes */
        bufnum += i;

        v = NULL;
        /* check for line continuation */
        if (bufnum >= 1) {
            /*
             * If we have bytes and the last char '\\' and second last char
             * is not '\\'
             */
            p = &(buff->data[bufnum - 1]);
            if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
                bufnum--;
                again = 1;
            }
        }
        if (again)
            continue;
        bufnum = 0;
        buf = buff->data;

        clear_comments(conf, buf);
        s = eat_ws(conf, buf);
        if (IS_EOF(conf, *s))
            continue;           /* blank line */
        if (*s == '[') {
            char *ss;

            s++;
            start = eat_ws(conf, s);
            ss = start;
 again:
            end = eat_alpha_numeric(conf, ss);
            p = eat_ws(conf, end);
            if (*p != ']') {
                if (*p != '\0' && ss != p) {
                    ss = p;
                    goto again;
                }
                CONFerr(CONF_F_DEF_LOAD_BIO,
                        CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
                goto err;
            }
            *end = '\0';
            if (!str_copy(conf, NULL, &section, start))
                goto err;
            if ((sv = _CONF_get_section(conf, section)) == NULL)
                sv = _CONF_new_section(conf, section);
            if (sv == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO,
                        CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
                goto err;
            }
            continue;
        } else {
            pname = s;
            end = eat_alpha_numeric(conf, s);
            if ((end[0] == ':') && (end[1] == ':')) {
                *end = '\0';
                end += 2;
                psection = pname;
                pname = end;
                end = eat_alpha_numeric(conf, end);
            } else {
                psection = section;
            }
            p = eat_ws(conf, end);
            if (strncmp(pname, ".include", 8) == 0
                && (p != pname + 8 || *p == '=')) {
                char *include = NULL;
                BIO *next;

                if (*p == '=') {
                    p++;
                    p = eat_ws(conf, p);
                }
                trim_ws(conf, p);
                if (!str_copy(conf, psection, &include, p))
                    goto err;
                /* get the BIO of the included file */
#ifndef OPENSSL_NO_POSIX_IO
                next = process_include(include, &dirctx, &dirpath);
                if (include != dirpath) {
                    /* dirpath will contain include in case of a directory */
                    OPENSSL_free(include);
                }
#else
                next = BIO_new_file(include, "r");
                OPENSSL_free(include);
#endif
                if (next != NULL) {
                    /* push the currently processing BIO onto stack */
                    if (biosk == NULL) {
                        if ((biosk = sk_BIO_new_null()) == NULL) {
                            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                            goto err;
                        }
                    }
                    if (!sk_BIO_push(biosk, in)) {
                        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                        goto err;
                    }
                    /* continue with reading from the included BIO */
                    in = next;
                }
                continue;
            } else if (*p != '=') {
                CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
                goto err;
            }
            *end = '\0';
            p++;
            start = eat_ws(conf, p);
            trim_ws(conf, start);

            if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            v->name = OPENSSL_strdup(pname);
            v->value = NULL;
            if (v->name == NULL) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            if (!str_copy(conf, psection, &(v->value), start))
                goto err;

            if (strcmp(psection, section) != 0) {
                if ((tv = _CONF_get_section(conf, psection))
                    == NULL)
                    tv = _CONF_new_section(conf, psection);
                if (tv == NULL) {
                    CONFerr(CONF_F_DEF_LOAD_BIO,
                            CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
                    goto err;
                }
            } else
                tv = sv;
            if (_CONF_add_string(conf, tv, v) == 0) {
                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            v = NULL;
        }
    }
    BUF_MEM_free(buff);
    OPENSSL_free(section);
    /*
     * No need to pop, since we only get here if the stack is empty.
     * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE!
     */
    sk_BIO_free(biosk);
    return 1;
 err:
    BUF_MEM_free(buff);
    OPENSSL_free(section);
    /*
     * Since |in| is the first element of the stack and should NOT be freed
     * here, we cannot use sk_BIO_pop_free().  Instead, we pop and free one
     * BIO at a time, making sure that the last one popped isn't.
     */
    while (sk_BIO_num(biosk) > 0) {
        BIO *popped = sk_BIO_pop(biosk);
        BIO_vfree(in);
        in = popped;
    }
    sk_BIO_free(biosk);
#ifndef OPENSSL_NO_POSIX_IO
    OPENSSL_free(dirpath);
    if (dirctx != NULL)
        OPENSSL_DIR_end(&dirctx);
#endif
    if (line != NULL)
        *line = eline;
    BIO_snprintf(btmp, sizeof(btmp), "%ld", eline);
    ERR_add_error_data(2, "line ", btmp);
    if (h != conf->data) {
        CONF_free(conf->data);
        conf->data = NULL;
    }
    if (v != NULL) {
        OPENSSL_free(v->name);
        OPENSSL_free(v->value);
        OPENSSL_free(v);
    }
    return 0;
}
Exemple #30
0
/**
 * Extract the optional PEM header, with details on the type of content and
 * any encryption used on the contents, and the bulk of the data from the bio.
 * The end of the header is marked by a blank line; if the end-of-input marker
 * is reached prior to a blank line, there is no header.
 *
 * The header and data arguments are BIO** since we may have to swap them
 * if there is no header, for efficiency.
 *
 * We need the name of the PEM-encoded type to verify the end string.
 */
static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name,
                               unsigned int flags)
{
    BIO *tmp = *header;
    char *linebuf, *p;
    int len, line, ret = 0, end = 0;
    /* 0 if not seen (yet), 1 if reading header, 2 if finished header */
    enum header_status got_header = MAYBE_HEADER;
    unsigned int flags_mask;
    size_t namelen;

    /* Need to hold trailing NUL (accounted for by BIO_gets() and the newline
     * that will be added by sanitize_line() (the extra '1'). */
    linebuf = pem_malloc(LINESIZE + 1, flags);
    if (linebuf == NULL) {
        PEMerr(PEM_F_GET_HEADER_AND_DATA, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    for (line = 0; ; line++) {
        flags_mask = ~0u;
        len = BIO_gets(bp, linebuf, LINESIZE);
        if (len <= 0) {
            PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_SHORT_HEADER);
            goto err;
        }

        if (got_header == MAYBE_HEADER) {
            if (memchr(linebuf, ':', len) != NULL)
                got_header = IN_HEADER;
        }
        if (!strncmp(linebuf, endstr, ENDLEN) || got_header == IN_HEADER)
            flags_mask &= ~PEM_FLAG_ONLY_B64;
        len = sanitize_line(linebuf, len, flags & flags_mask);

        /* Check for end of header. */
        if (linebuf[0] == '\n') {
            if (got_header == POST_HEADER) {
                /* Another blank line is an error. */
                PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
                goto err;
            }
            got_header = POST_HEADER;
            tmp = *data;
            continue;
        }

        /* Check for end of stream (which means there is no header). */
        if (strncmp(linebuf, endstr, ENDLEN) == 0) {
            p = linebuf + ENDLEN;
            namelen = strlen(name);
            if (strncmp(p, name, namelen) != 0 ||
                strncmp(p + namelen, tailstr, TAILLEN) != 0) {
                PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
                goto err;
            }
            if (got_header == MAYBE_HEADER) {
                *header = *data;
                *data = tmp;
            }
            break;
        } else if (end) {
            /* Malformed input; short line not at end of data. */
            PEMerr(PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE);
            goto err;
        }
        /*
         * Else, a line of text -- could be header or data; we don't
         * know yet.  Just pass it through.
         */
        if (BIO_puts(tmp, linebuf) < 0)
            goto err;
        /*
         * Only encrypted files need the line length check applied.
         */
        if (got_header == POST_HEADER) {
            /* 65 includes the trailing newline */
            if (len > 65)
                goto err;
            if (len < 65)
                end = 1;
        }
    }

    ret = 1;
err:
    pem_free(linebuf, flags, LINESIZE + 1);
    return ret;
}