示例#1
0
文件: connect.c 项目: RobinWuDev/Qt
static int conn_state(BIO *bio, BIO_CONNECT *c) {
  int ret = -1, i;
  char *p, *q;
  int (*cb)(const BIO *, int, int) = NULL;

  if (c->info_callback != NULL) {
    cb = c->info_callback;
  }

  for (;;) {
    switch (c->state) {
      case BIO_CONN_S_BEFORE:
        p = c->param_hostname;
        if (p == NULL) {
          OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_HOSTNAME_SPECIFIED);
          goto exit_loop;
        }
        for (; *p != 0; p++) {
          if (*p == ':' || *p == '/') {
            break;
          }
        }

        i = *p;
        if (i == ':' || i == '/') {
          *(p++) = 0;
          if (i == ':') {
            for (q = p; *q; q++) {
              if (*q == '/') {
                *q = 0;
                break;
              }
            }
            if (c->param_port != NULL) {
              OPENSSL_free(c->param_port);
            }
            c->param_port = BUF_strdup(p);
          }
        }

        if (c->param_port == NULL) {
          OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NO_PORT_SPECIFIED);
          ERR_add_error_data(2, "host=", c->param_hostname);
          goto exit_loop;
        }

        if (!bio_ip_and_port_to_socket_and_addr(
                &bio->num, &c->them, &c->them_length, c->param_hostname,
                c->param_port)) {
          OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_UNABLE_TO_CREATE_SOCKET);
          ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
          goto exit_loop;
        }

        memset(c->ip, 0, 4);
        maybe_copy_ipv4_address(c->ip, &c->them);

        if (c->nbio) {
          if (!bio_socket_nbio(bio->num, 1)) {
            OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_ERROR_SETTING_NBIO);
            ERR_add_error_data(4, "host=", c->param_hostname, ":",
                               c->param_port);
            goto exit_loop;
          }
        }

        i = 1;
        ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
                         sizeof(i));
        if (ret < 0) {
          OPENSSL_PUT_SYSTEM_ERROR(setsockopt);
          OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_KEEPALIVE);
          ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
          goto exit_loop;
        }

        BIO_clear_retry_flags(bio);
        ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
        if (ret < 0) {
          if (bio_fd_should_retry(ret)) {
            BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
            c->state = BIO_CONN_S_BLOCKED_CONNECT;
            bio->retry_reason = BIO_RR_CONNECT;
          } else {
            OPENSSL_PUT_SYSTEM_ERROR(connect);
            OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_CONNECT_ERROR);
            ERR_add_error_data(4, "host=", c->param_hostname, ":",
                               c->param_port);
          }
          goto exit_loop;
        } else {
          c->state = BIO_CONN_S_OK;
        }
        break;

      case BIO_CONN_S_BLOCKED_CONNECT:
        i = bio_sock_error(bio->num);
        if (i) {
          if (bio_fd_should_retry(ret)) {
            BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
            c->state = BIO_CONN_S_BLOCKED_CONNECT;
            bio->retry_reason = BIO_RR_CONNECT;
            ret = -1;
          } else {
            BIO_clear_retry_flags(bio);
            OPENSSL_PUT_SYSTEM_ERROR(connect);
            OPENSSL_PUT_ERROR(BIO, conn_state, BIO_R_NBIO_CONNECT_ERROR);
            ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
            ret = 0;
          }
          goto exit_loop;
        } else {
          c->state = BIO_CONN_S_OK;
        }
        break;

      case BIO_CONN_S_OK:
        ret = 1;
        goto exit_loop;
      default:
        assert(0);
        goto exit_loop;
    }

    if (cb != NULL) {
      ret = cb((BIO *)bio, c->state, ret);
      if (ret == 0) {
        goto end;
      }
    }
  }

exit_loop:
  if (cb != NULL) {
    ret = cb((BIO *)bio, c->state, ret);
  }

end:
  return ret;
}
示例#2
0
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short length;
	unsigned short type;
	unsigned short size;
	unsigned char *data = *p;
	int tlsext_servername = 0;
	int renegotiate_seen = 0;

	if (data >= (d+n-2))
		goto ri_check;

	n2s(data,length);
	if (data+length != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	while(data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		goto ri_check;

		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 1, type, data, size,
						s->tlsext_debug_arg);

		if (type == TLSEXT_TYPE_server_name)
			{
			if (s->tlsext_hostname == NULL || size > 0)
				{
				*al = TLS1_AD_UNRECOGNIZED_NAME;
				return 0;
				}
			tlsext_servername = 1;   
			}
		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
				|| (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			s->tlsext_ticket_expected = 1;
			}
		else if (type == TLSEXT_TYPE_status_request &&
		         s->version != DTLS1_VERSION)
			{
			/* MUST be empty and only sent if we've requested
			 * a status request message.
			 */ 
			if ((s->tlsext_status_type == -1) || (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			/* Set flag to expect CertificateStatus message */
			s->tlsext_status_expected = 1;
			}
		else if (type == TLSEXT_TYPE_renegotiate)
			{
			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
				return 0;
			renegotiate_seen = 1;
			}
		data+=size;		
		}

	if (data != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	if (!s->hit && tlsext_servername == 1)
		{
 		if (s->tlsext_hostname)
			{
			if (s->session->tlsext_hostname == NULL)
				{
				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
				if (!s->session->tlsext_hostname)
					{
					*al = SSL_AD_UNRECOGNIZED_NAME;
					return 0;
					}
				}
			else 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			}
		}

	*p = data;

	ri_check:

	/* Determine if we need to see RI. Strictly speaking if we want to
	 * avoid an attack we should *always* see RI even on initial server
	 * hello because the client doesn't see any renegotiation during an
	 * attack. However this would mean we could not connect to any server
	 * which doesn't support RI so for the immediate future tolerate RI
	 * absence on initial connect only.
	 */
	if (!renegotiate_seen
		&& !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
		&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
		{
		*al = SSL_AD_HANDSHAKE_FAILURE;
		SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT,
				SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
		return 0;
		}

	return 1;
	}
示例#3
0
static long set_HWCRHK_LIBNAME(const char *name)
	{
	free_HWCRHK_LIBNAME();
	return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
示例#4
0
static long set_NURON_LIBNAME(const char *name)
	{
	free_NURON_LIBNAME();
	return (((NURON_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
示例#5
0
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
                                        const char *pem_str, const char *info)
{
    EVP_PKEY_ASN1_METHOD *ameth;
    ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
    if (!ameth)
        return NULL;

    memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));

    ameth->pkey_id = id;
    ameth->pkey_base_id = id;
    ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;

    if (info) {
        ameth->info = BUF_strdup(info);
        if (!ameth->info)
            goto err;
    } else
        ameth->info = NULL;

    if (pem_str) {
        ameth->pem_str = BUF_strdup(pem_str);
        if (!ameth->pem_str)
            goto err;
    } else
        ameth->pem_str = NULL;

    ameth->pub_decode = 0;
    ameth->pub_encode = 0;
    ameth->pub_cmp = 0;
    ameth->pub_print = 0;

    ameth->priv_decode = 0;
    ameth->priv_encode = 0;
    ameth->priv_print = 0;

    ameth->old_priv_encode = 0;
    ameth->old_priv_decode = 0;

    ameth->item_verify = 0;
    ameth->item_sign = 0;

    ameth->pkey_size = 0;
    ameth->pkey_bits = 0;

    ameth->param_decode = 0;
    ameth->param_encode = 0;
    ameth->param_missing = 0;
    ameth->param_copy = 0;
    ameth->param_cmp = 0;
    ameth->param_print = 0;

    ameth->pkey_free = 0;
    ameth->pkey_ctrl = 0;

    return ameth;

 err:

    EVP_PKEY_asn1_free(ameth);
    return NULL;

}
示例#6
0
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
  int *ip;
  long ret = 1;
  BIO_CONNECT *data;

  data = (BIO_CONNECT *)bio->ptr;

  switch (cmd) {
    case BIO_CTRL_RESET:
      ret = 0;
      data->state = BIO_CONN_S_BEFORE;
      conn_close_socket(bio);
      bio->flags = 0;
      break;
    case BIO_C_DO_STATE_MACHINE:
      // use this one to start the connection
      if (data->state != BIO_CONN_S_OK) {
        ret = (long)conn_state(bio, data);
      } else {
        ret = 1;
      }
      break;
    case BIO_C_SET_CONNECT:
      if (ptr != NULL) {
        bio->init = 1;
        if (num == 0) {
          OPENSSL_free(data->param_hostname);
          data->param_hostname = BUF_strdup(ptr);
          if (data->param_hostname == NULL) {
            ret = 0;
          }
        } else if (num == 1) {
          OPENSSL_free(data->param_port);
          data->param_port = BUF_strdup(ptr);
          if (data->param_port == NULL) {
            ret = 0;
          }
        } else {
          ret = 0;
        }
      }
      break;
    case BIO_C_SET_NBIO:
      data->nbio = (int)num;
      break;
    case BIO_C_GET_FD:
      if (bio->init) {
        ip = (int *)ptr;
        if (ip != NULL) {
          *ip = bio->num;
        }
        ret = bio->num;
      } else {
        ret = -1;
      }
      break;
    case BIO_CTRL_GET_CLOSE:
      ret = bio->shutdown;
      break;
    case BIO_CTRL_SET_CLOSE:
      bio->shutdown = (int)num;
      break;
    case BIO_CTRL_PENDING:
    case BIO_CTRL_WPENDING:
      ret = 0;
      break;
    case BIO_CTRL_FLUSH:
      break;
    case BIO_CTRL_GET_CALLBACK: {
      int (**fptr)(const BIO *bio, int state, int xret);
      fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
      *fptr = data->info_callback;
    } break;
    default:
      ret = 0;
      break;
  }
  return ret;
}
示例#7
0
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
	{
	unsigned short type;
	unsigned short size;
	unsigned short len;  
	unsigned char *data = *p;

	int tlsext_servername = 0;

	if (data >= (d+n-2))
		return 1;

	n2s(data,len);

	while(data <= (d+n-4))
		{
		n2s(data,type);
		n2s(data,size);

		if (data+size > (d+n))
	   		return 1;

		if (s->tlsext_debug_cb)
			s->tlsext_debug_cb(s, 1, type, data, size,
						s->tlsext_debug_arg);

		if (type == TLSEXT_TYPE_server_name)
			{
			if (s->tlsext_hostname == NULL || size > 0)
				{
				*al = TLS1_AD_UNRECOGNIZED_NAME;
				return 0;
				}
			tlsext_servername = 1;   
			}
		else if (type == TLSEXT_TYPE_session_ticket)
			{
			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
				|| (size > 0))
				{
				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
				return 0;
				}
			s->tlsext_ticket_expected = 1;
			}

		data+=size;		
		}

	if (data != d+n)
		{
		*al = SSL_AD_DECODE_ERROR;
		return 0;
		}

	if (!s->hit && tlsext_servername == 1)
		{
 		if (s->tlsext_hostname)
			{
			if (s->session->tlsext_hostname == NULL)
				{
				s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);	
				if (!s->session->tlsext_hostname)
					{
					*al = SSL_AD_UNRECOGNIZED_NAME;
					return 0;
					}
				}
			else 
				{
				*al = SSL_AD_DECODE_ERROR;
				return 0;
				}
			}
		}

	*p = data;
	return 1;
	}
示例#8
0
static long set_ATALLA_LIBNAME(const char *name)
	{
	free_ATALLA_LIBNAME();
	return (((ATALLA_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
示例#9
0
static int conn_state(BIO *b, BIO_CONNECT *c)
	{
	int ret= -1,i;
	unsigned long l;
	char *p,*q;
	int (*cb)()=NULL;

	if (c->info_callback != NULL)
		cb=c->info_callback;

	for (;;)
		{
		switch (c->state)
			{
		case BIO_CONN_S_BEFORE:
			p=c->param_hostname;
			if (p == NULL)
				{
				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED);
				goto exit_loop;
				}
			for ( ; *p != '\0'; p++)
				{
				if ((*p == ':') || (*p == '/')) break;
				}

			i= *p;
			if ((i == ':') || (i == '/'))
				{

				*(p++)='\0';
				if (i == ':')
					{
					for (q=p; *q; q++)
						if (*q == '/')
							{
							*q='\0';
							break;
							}
					if (c->param_port != NULL)
						OPENSSL_free(c->param_port);
					c->param_port=BUF_strdup(p);
					}
				}

			if (c->param_port == NULL)
				{
				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
				ERR_add_error_data(2,"host=",c->param_hostname);
				goto exit_loop;
				}
			c->state=BIO_CONN_S_GET_IP;
			break;

		case BIO_CONN_S_GET_IP:
			if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
				goto exit_loop;
			c->state=BIO_CONN_S_GET_PORT;
			break;

		case BIO_CONN_S_GET_PORT:
			if (c->param_port == NULL)
				{
				/* abort(); */
				goto exit_loop;
				}
			else if (BIO_get_port(c->param_port,&c->port) <= 0)
				goto exit_loop;
			c->state=BIO_CONN_S_CREATE_SOCKET;
			break;

		case BIO_CONN_S_CREATE_SOCKET:
			/* now setup address */
			memset((char *)&c->them,0,sizeof(c->them));
			c->them.sin_family=AF_INET;
			c->them.sin_port=htons((unsigned short)c->port);
			l=(unsigned long)
				((unsigned long)c->ip[0]<<24L)|
				((unsigned long)c->ip[1]<<16L)|
				((unsigned long)c->ip[2]<< 8L)|
				((unsigned long)c->ip[3]);
			c->them.sin_addr.s_addr=htonl(l);
			c->state=BIO_CONN_S_CREATE_SOCKET;

			ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
			if (ret == INVALID_SOCKET)
				{
				SYSerr(SYS_F_SOCKET,get_last_socket_error());
				ERR_add_error_data(4,"host=",c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
				goto exit_loop;
				}
			b->num=ret;
			c->state=BIO_CONN_S_NBIO;
			break;

		case BIO_CONN_S_NBIO:
			if (c->nbio)
				{
				if (!BIO_socket_nbio(b->num,1))
					{
					BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
					ERR_add_error_data(4,"host=",
						c->param_hostname,
						":",c->param_port);
					goto exit_loop;
					}
				}
			c->state=BIO_CONN_S_CONNECT;

#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
			i=1;
			i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
			if (i < 0)
				{
				SYSerr(SYS_F_SOCKET,get_last_socket_error());
				ERR_add_error_data(4,"host=",c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
				goto exit_loop;
				}
#endif
			break;

		case BIO_CONN_S_CONNECT:
			BIO_clear_retry_flags(b);
			ret=connect(b->num,
				(struct sockaddr *)&c->them,
				sizeof(c->them));
			b->retry_reason=0;
			if (ret < 0)
				{
				if (BIO_sock_should_retry(ret))
					{
					BIO_set_retry_special(b);
					c->state=BIO_CONN_S_BLOCKED_CONNECT;
					b->retry_reason=BIO_RR_CONNECT;
					}
				else
					{
					SYSerr(SYS_F_CONNECT,get_last_socket_error());
					ERR_add_error_data(4,"host=",
						c->param_hostname,
						":",c->param_port);
					BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
					}
				goto exit_loop;
				}
			else
				c->state=BIO_CONN_S_OK;
			break;

		case BIO_CONN_S_BLOCKED_CONNECT:
			i=BIO_sock_error(b->num);
			if (i)
				{
				BIO_clear_retry_flags(b);
				SYSerr(SYS_F_CONNECT,i);
				ERR_add_error_data(4,"host=",
					c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
				ret=0;
				goto exit_loop;
				}
			else
				c->state=BIO_CONN_S_OK;
			break;

		case BIO_CONN_S_OK:
			ret=1;
			goto exit_loop;
		default:
			/* abort(); */
			goto exit_loop;
			}

		if (cb != NULL)
			{
			if (!(ret=cb((BIO *)b,c->state,ret)))
				goto end;
			}
		}

	/* Loop does not exit */
exit_loop:
	if (cb != NULL)
		ret=cb((BIO *)b,c->state,ret);
end:
	return(ret);
	}
示例#10
0
int BIO_get_accept_socket(char *host, int bind_mode)
	{
	int ret=0;
	union {
		struct sockaddr sa;
		struct sockaddr_in sa_in;
#if OPENSSL_USE_IPV6
		struct sockaddr_in6 sa_in6;
#endif
	} server,client;
	int s=INVALID_SOCKET,cs;
	unsigned char ip[4];
	unsigned short port;
	char *str=NULL,*e;
	char *h,*p;
	unsigned long l;
	int err_num;

	if (BIO_sock_init() != 1) return(INVALID_SOCKET);

	if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);

	h=p=NULL;
	h=str;
	for (e=str; *e; e++)
		{
		if (*e == ':')
			{
			p=e;
			}
		else if (*e == '/')
			{
			*e='\0';
			break;
			}
		}
	if (p)	*p++='\0';	/* points at last ':', '::port' is special [see below] */
	else	p=h,h=NULL;

#ifdef EAI_FAMILY
	do {
	static union {	void *p;
			int (*f)(const char *,const char *,
				 const struct addrinfo *,
				 struct addrinfo **);
			} p_getaddrinfo = {NULL};
	static union {	void *p;
			void (*f)(struct addrinfo *);
			} p_freeaddrinfo = {NULL};
	struct addrinfo *res,hint;

	if (p_getaddrinfo.p==NULL)
		{
		if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL ||
		    (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL)
			p_getaddrinfo.p=(void*)-1;
		}
	if (p_getaddrinfo.p==(void *)-1) break;

	/* '::port' enforces IPv6 wildcard listener. Some OSes,
	 * e.g. Solaris, default to IPv6 without any hint. Also
	 * note that commonly IPv6 wildchard socket can service
	 * IPv4 connections just as well...  */
	memset(&hint,0,sizeof(hint));
	if (h)
		{
		if (strchr(h,':'))
			{
			if (h[1]=='\0') h=NULL;
#if OPENSSL_USE_IPV6
			hint.ai_family = AF_INET6;
#else
			h=NULL;
#endif
			}
	    	else if (h[0]=='*' && h[1]=='\0')
			h=NULL;
		}

	if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break;

	memcpy(&server, res->ai_addr,
		res->ai_addrlen<=sizeof(server)?res->ai_addrlen:sizeof(server));

	(*p_freeaddrinfo.f)(res);
	goto again;
	} while (0);
#endif

	if (!BIO_get_port(p,&port)) goto err;

	memset((char *)&server,0,sizeof(server));
	server.sa_in.sin_family=AF_INET;
	server.sa_in.sin_port=htons(port);

	if (h == NULL || strcmp(h,"*") == 0)
		server.sa_in.sin_addr.s_addr=INADDR_ANY;
	else
		{
                if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
		l=(unsigned long)
			((unsigned long)ip[0]<<24L)|
			((unsigned long)ip[1]<<16L)|
			((unsigned long)ip[2]<< 8L)|
			((unsigned long)ip[3]);
		server.sa_in.sin_addr.s_addr=htonl(l);
		}

again:
	s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
	if (s == INVALID_SOCKET)
		{
		SYSerr(SYS_F_SOCKET,get_last_socket_error());
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
		goto err;
		}

#ifdef SO_REUSEADDR
	if (bind_mode == BIO_BIND_REUSEADDR)
		{
		int i=1;

		ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
		bind_mode=BIO_BIND_NORMAL;
		}
#endif
	if (bind(s,&server.sa,sizeof(server)) == -1)
		{
#ifdef SO_REUSEADDR
		err_num=get_last_socket_error();
		if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
			(err_num == EADDRINUSE))
			{
			client = server;
			if (h == NULL || strcmp(h,"*") == 0)
				{
#if OPENSSL_USE_IPV6
				if (client.sa.sa_family == AF_INET6)
					{
					memset(&client.sa_in6.sin6_addr,0,sizeof(client.sa_in6.sin6_addr));
					client.sa_in6.sin6_addr.s6_addr[15]=1;
					}
				else
#endif
				if (client.sa.sa_family == AF_INET)
					{
					client.sa_in.sin_addr.s_addr=htonl(0x7F000001);
					}
				else	goto err;
				}
			cs=socket(client.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
			if (cs != INVALID_SOCKET)
				{
				int ii;
				ii=connect(cs,&client.sa,sizeof(client));
				closesocket(cs);
				if (ii == INVALID_SOCKET)
					{
					bind_mode=BIO_BIND_REUSEADDR;
					closesocket(s);
					goto again;
					}
				/* else error */
				}
			/* else error */
			}
#endif
		SYSerr(SYS_F_BIND,err_num);
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
		goto err;
		}
	if (listen(s,MAX_LISTEN) == -1)
		{
		SYSerr(SYS_F_BIND,get_last_socket_error());
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
		goto err;
		}
	ret=1;
err:
	if (str != NULL) OPENSSL_free(str);
	if ((ret == 0) && (s != INVALID_SOCKET))
		{
		closesocket(s);
		s= INVALID_SOCKET;
		}
	return(s);
	}
示例#11
0
文件: cms.c 项目: 5y/node
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    int operation = 0;
    int ret = 0;
    char **args;
    const char *inmode = "r", *outmode = "w";
    char *infile = NULL, *outfile = NULL, *rctfile = NULL;
    char *signerfile = NULL, *recipfile = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
    char *certsoutfile = NULL;
    const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
    CMS_ContentInfo *cms = NULL, *rcms = NULL;
    X509_STORE *store = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    EVP_PKEY *key = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
    int badarg = 0;
    int flags = CMS_DETACHED, noout = 0, print = 0;
    int verify_retcode = 0;
    int rr_print = 0, rr_allorfirst = -1;
    STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
    CMS_ReceiptRequest *rr = NULL;
    char *to = NULL, *from = NULL, *subject = NULL;
    char *CAfile = NULL, *CApath = NULL;
    char *passargin = NULL, *passin = NULL;
    char *inrand = NULL;
    int need_rand = 0;
    const EVP_MD *sign_md = NULL;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
    int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
# ifndef OPENSSL_NO_ENGINE
    char *engine = NULL;
# endif
    unsigned char *secret_key = NULL, *secret_keyid = NULL;
    unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
    size_t secret_keylen = 0, secret_keyidlen = 0;

    cms_key_param *key_first = NULL, *key_param = NULL;

    ASN1_OBJECT *econtent_type = NULL;

    X509_VERIFY_PARAM *vpm = NULL;

    args = argv + 1;
    ret = 1;

    apps_startup();

    if (bio_err == NULL) {
        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
    }

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

    while (!badarg && *args && *args[0] == '-') {
        if (!strcmp(*args, "-encrypt"))
            operation = SMIME_ENCRYPT;
        else if (!strcmp(*args, "-decrypt"))
            operation = SMIME_DECRYPT;
        else if (!strcmp(*args, "-sign"))
            operation = SMIME_SIGN;
        else if (!strcmp(*args, "-sign_receipt"))
            operation = SMIME_SIGN_RECEIPT;
        else if (!strcmp(*args, "-resign"))
            operation = SMIME_RESIGN;
        else if (!strcmp(*args, "-verify"))
            operation = SMIME_VERIFY;
        else if (!strcmp(*args, "-verify_retcode"))
            verify_retcode = 1;
        else if (!strcmp(*args, "-verify_receipt")) {
            operation = SMIME_VERIFY_RECEIPT;
            if (!args[1])
                goto argerr;
            args++;
            rctfile = *args;
        } else if (!strcmp(*args, "-cmsout"))
            operation = SMIME_CMSOUT;
        else if (!strcmp(*args, "-data_out"))
            operation = SMIME_DATAOUT;
        else if (!strcmp(*args, "-data_create"))
            operation = SMIME_DATA_CREATE;
        else if (!strcmp(*args, "-digest_verify"))
            operation = SMIME_DIGEST_VERIFY;
        else if (!strcmp(*args, "-digest_create"))
            operation = SMIME_DIGEST_CREATE;
        else if (!strcmp(*args, "-compress"))
            operation = SMIME_COMPRESS;
        else if (!strcmp(*args, "-uncompress"))
            operation = SMIME_UNCOMPRESS;
        else if (!strcmp(*args, "-EncryptedData_decrypt"))
            operation = SMIME_ENCRYPTED_DECRYPT;
        else if (!strcmp(*args, "-EncryptedData_encrypt"))
            operation = SMIME_ENCRYPTED_ENCRYPT;
# ifndef OPENSSL_NO_DES
        else if (!strcmp(*args, "-des3"))
            cipher = EVP_des_ede3_cbc();
        else if (!strcmp(*args, "-des"))
            cipher = EVP_des_cbc();
        else if (!strcmp(*args, "-des3-wrap"))
            wrap_cipher = EVP_des_ede3_wrap();
# endif
# ifndef OPENSSL_NO_SEED
        else if (!strcmp(*args, "-seed"))
            cipher = EVP_seed_cbc();
# endif
# ifndef OPENSSL_NO_RC2
        else if (!strcmp(*args, "-rc2-40"))
            cipher = EVP_rc2_40_cbc();
        else if (!strcmp(*args, "-rc2-128"))
            cipher = EVP_rc2_cbc();
        else if (!strcmp(*args, "-rc2-64"))
            cipher = EVP_rc2_64_cbc();
# endif
# ifndef OPENSSL_NO_AES
        else if (!strcmp(*args, "-aes128"))
            cipher = EVP_aes_128_cbc();
        else if (!strcmp(*args, "-aes192"))
            cipher = EVP_aes_192_cbc();
        else if (!strcmp(*args, "-aes256"))
            cipher = EVP_aes_256_cbc();
        else if (!strcmp(*args, "-aes128-wrap"))
            wrap_cipher = EVP_aes_128_wrap();
        else if (!strcmp(*args, "-aes192-wrap"))
            wrap_cipher = EVP_aes_192_wrap();
        else if (!strcmp(*args, "-aes256-wrap"))
            wrap_cipher = EVP_aes_256_wrap();
# endif
# ifndef OPENSSL_NO_CAMELLIA
        else if (!strcmp(*args, "-camellia128"))
            cipher = EVP_camellia_128_cbc();
        else if (!strcmp(*args, "-camellia192"))
            cipher = EVP_camellia_192_cbc();
        else if (!strcmp(*args, "-camellia256"))
            cipher = EVP_camellia_256_cbc();
# endif
        else if (!strcmp(*args, "-debug_decrypt"))
            flags |= CMS_DEBUG_DECRYPT;
        else if (!strcmp(*args, "-text"))
            flags |= CMS_TEXT;
        else if (!strcmp(*args, "-nointern"))
            flags |= CMS_NOINTERN;
        else if (!strcmp(*args, "-noverify")
                 || !strcmp(*args, "-no_signer_cert_verify"))
            flags |= CMS_NO_SIGNER_CERT_VERIFY;
        else if (!strcmp(*args, "-nocerts"))
            flags |= CMS_NOCERTS;
        else if (!strcmp(*args, "-noattr"))
            flags |= CMS_NOATTR;
        else if (!strcmp(*args, "-nodetach"))
            flags &= ~CMS_DETACHED;
        else if (!strcmp(*args, "-nosmimecap"))
            flags |= CMS_NOSMIMECAP;
        else if (!strcmp(*args, "-binary"))
            flags |= CMS_BINARY;
        else if (!strcmp(*args, "-keyid"))
            flags |= CMS_USE_KEYID;
        else if (!strcmp(*args, "-nosigs"))
            flags |= CMS_NOSIGS;
        else if (!strcmp(*args, "-no_content_verify"))
            flags |= CMS_NO_CONTENT_VERIFY;
        else if (!strcmp(*args, "-no_attr_verify"))
            flags |= CMS_NO_ATTR_VERIFY;
        else if (!strcmp(*args, "-stream"))
            flags |= CMS_STREAM;
        else if (!strcmp(*args, "-indef"))
            flags |= CMS_STREAM;
        else if (!strcmp(*args, "-noindef"))
            flags &= ~CMS_STREAM;
        else if (!strcmp(*args, "-nooldmime"))
            flags |= CMS_NOOLDMIMETYPE;
        else if (!strcmp(*args, "-crlfeol"))
            flags |= CMS_CRLFEOL;
        else if (!strcmp(*args, "-noout"))
            noout = 1;
        else if (!strcmp(*args, "-receipt_request_print"))
            rr_print = 1;
        else if (!strcmp(*args, "-receipt_request_all"))
            rr_allorfirst = 0;
        else if (!strcmp(*args, "-receipt_request_first"))
            rr_allorfirst = 1;
        else if (!strcmp(*args, "-receipt_request_from")) {
            if (!args[1])
                goto argerr;
            args++;
            if (!rr_from)
                rr_from = sk_OPENSSL_STRING_new_null();
            sk_OPENSSL_STRING_push(rr_from, *args);
        } else if (!strcmp(*args, "-receipt_request_to")) {
            if (!args[1])
                goto argerr;
            args++;
            if (!rr_to)
                rr_to = sk_OPENSSL_STRING_new_null();
            sk_OPENSSL_STRING_push(rr_to, *args);
        } else if (!strcmp(*args, "-print")) {
            noout = 1;
            print = 1;
        } else if (!strcmp(*args, "-secretkey")) {
            long ltmp;
            if (!args[1])
                goto argerr;
            args++;
            secret_key = string_to_hex(*args, &ltmp);
            if (!secret_key) {
                BIO_printf(bio_err, "Invalid key %s\n", *args);
                goto argerr;
            }
            secret_keylen = (size_t)ltmp;
        } else if (!strcmp(*args, "-secretkeyid")) {
            long ltmp;
            if (!args[1])
                goto argerr;
            args++;
            secret_keyid = string_to_hex(*args, &ltmp);
            if (!secret_keyid) {
                BIO_printf(bio_err, "Invalid id %s\n", *args);
                goto argerr;
            }
            secret_keyidlen = (size_t)ltmp;
        } else if (!strcmp(*args, "-pwri_password")) {
            if (!args[1])
                goto argerr;
            args++;
            pwri_pass = (unsigned char *)*args;
        } else if (!strcmp(*args, "-econtent_type")) {
            if (!args[1])
                goto argerr;
            args++;
            econtent_type = OBJ_txt2obj(*args, 0);
            if (!econtent_type) {
                BIO_printf(bio_err, "Invalid OID %s\n", *args);
                goto argerr;
            }
        } else if (!strcmp(*args, "-rand")) {
            if (!args[1])
                goto argerr;
            args++;
            inrand = *args;
            need_rand = 1;
        }
# ifndef OPENSSL_NO_ENGINE
        else if (!strcmp(*args, "-engine")) {
            if (!args[1])
                goto argerr;
            engine = *++args;
        }
# endif
        else if (!strcmp(*args, "-passin")) {
            if (!args[1])
                goto argerr;
            passargin = *++args;
        } else if (!strcmp(*args, "-to")) {
            if (!args[1])
                goto argerr;
            to = *++args;
        } else if (!strcmp(*args, "-from")) {
            if (!args[1])
                goto argerr;
            from = *++args;
        } else if (!strcmp(*args, "-subject")) {
            if (!args[1])
                goto argerr;
            subject = *++args;
        } else if (!strcmp(*args, "-signer")) {
            if (!args[1])
                goto argerr;
            /* If previous -signer argument add signer to list */

            if (signerfile) {
                if (!sksigners)
                    sksigners = sk_OPENSSL_STRING_new_null();
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (!keyfile)
                    keyfile = signerfile;
                if (!skkeys)
                    skkeys = sk_OPENSSL_STRING_new_null();
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = *++args;
        } else if (!strcmp(*args, "-recip")) {
            if (!args[1])
                goto argerr;
            if (operation == SMIME_ENCRYPT) {
                if (!encerts)
                    encerts = sk_X509_new_null();
                cert = load_cert(bio_err, *++args, FORMAT_PEM,
                                 NULL, e, "recipient certificate file");
                if (!cert)
                    goto end;
                sk_X509_push(encerts, cert);
                cert = NULL;
            } else
                recipfile = *++args;
        } else if (!strcmp(*args, "-certsout")) {
            if (!args[1])
                goto argerr;
            certsoutfile = *++args;
        } else if (!strcmp(*args, "-md")) {
            if (!args[1])
                goto argerr;
            sign_md = EVP_get_digestbyname(*++args);
            if (sign_md == NULL) {
                BIO_printf(bio_err, "Unknown digest %s\n", *args);
                goto argerr;
            }
        } else if (!strcmp(*args, "-inkey")) {
            if (!args[1])
                goto argerr;
            /* If previous -inkey arument add signer to list */
            if (keyfile) {
                if (!signerfile) {
                    BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    goto argerr;
                }
                if (!sksigners)
                    sksigners = sk_OPENSSL_STRING_new_null();
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (!skkeys)
                    skkeys = sk_OPENSSL_STRING_new_null();
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = *++args;
        } else if (!strcmp(*args, "-keyform")) {
            if (!args[1])
                goto argerr;
            keyform = str2fmt(*++args);
        } else if (!strcmp(*args, "-keyopt")) {
            int keyidx = -1;
            if (!args[1])
                goto argerr;
            if (operation == SMIME_ENCRYPT) {
                if (encerts)
                    keyidx += sk_X509_num(encerts);
            } else {
                if (keyfile || signerfile)
                    keyidx++;
                if (skkeys)
                    keyidx += sk_OPENSSL_STRING_num(skkeys);
            }
            if (keyidx < 0) {
                BIO_printf(bio_err, "No key specified\n");
                goto argerr;
            }
            if (key_param == NULL || key_param->idx != keyidx) {
                cms_key_param *nparam;
                nparam = OPENSSL_malloc(sizeof(cms_key_param));
                if(!nparam) {
                    BIO_printf(bio_err, "Out of memory\n");
                    goto argerr;
                }
                nparam->idx = keyidx;
                nparam->param = sk_OPENSSL_STRING_new_null();
                nparam->next = NULL;
                if (key_first == NULL)
                    key_first = nparam;
                else
                    key_param->next = nparam;
                key_param = nparam;
            }
            sk_OPENSSL_STRING_push(key_param->param, *++args);
        } else if (!strcmp(*args, "-rctform")) {
            if (!args[1])
                goto argerr;
            rctformat = str2fmt(*++args);
        } else if (!strcmp(*args, "-certfile")) {
            if (!args[1])
                goto argerr;
            certfile = *++args;
        } else if (!strcmp(*args, "-CAfile")) {
            if (!args[1])
                goto argerr;
            CAfile = *++args;
        } else if (!strcmp(*args, "-CApath")) {
            if (!args[1])
                goto argerr;
            CApath = *++args;
        } else if (!strcmp(*args, "-in")) {
            if (!args[1])
                goto argerr;
            infile = *++args;
        } else if (!strcmp(*args, "-inform")) {
            if (!args[1])
                goto argerr;
            informat = str2fmt(*++args);
        } else if (!strcmp(*args, "-outform")) {
            if (!args[1])
                goto argerr;
            outformat = str2fmt(*++args);
        } else if (!strcmp(*args, "-out")) {
            if (!args[1])
                goto argerr;
            outfile = *++args;
        } else if (!strcmp(*args, "-content")) {
            if (!args[1])
                goto argerr;
            contfile = *++args;
        } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
            continue;
        else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
            badarg = 1;
        args++;
    }

    if (((rr_allorfirst != -1) || rr_from) && !rr_to) {
        BIO_puts(bio_err, "No Signed Receipts Recipients\n");
        goto argerr;
    }

    if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) {
        BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
        goto argerr;
    }
    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto argerr;
    }

    if (operation & SMIME_SIGNERS) {
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto argerr;
        }
        /* Check to see if any final signer needs to be appended */
        if (signerfile) {
            if (!sksigners)
                sksigners = sk_OPENSSL_STRING_new_null();
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys)
                skkeys = sk_OPENSSL_STRING_new_null();
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            badarg = 1;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    }

    else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile && !secret_key && !pwri_pass) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            badarg = 1;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (!*args && !secret_key && !pwri_pass && !encerts) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            badarg = 1;
        }
        need_rand = 1;
    } else if (!operation)
        badarg = 1;

    if (badarg) {
 argerr:
        BIO_printf(bio_err, "Usage cms [options] cert.pem ...\n");
        BIO_printf(bio_err, "where options are\n");
        BIO_printf(bio_err, "-encrypt       encrypt message\n");
        BIO_printf(bio_err, "-decrypt       decrypt encrypted message\n");
        BIO_printf(bio_err, "-sign          sign message\n");
        BIO_printf(bio_err, "-verify        verify signed message\n");
        BIO_printf(bio_err, "-cmsout        output CMS structure\n");
# ifndef OPENSSL_NO_DES
        BIO_printf(bio_err, "-des3          encrypt with triple DES\n");
        BIO_printf(bio_err, "-des           encrypt with DES\n");
# endif
# ifndef OPENSSL_NO_SEED
        BIO_printf(bio_err, "-seed          encrypt with SEED\n");
# endif
# ifndef OPENSSL_NO_RC2
        BIO_printf(bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
        BIO_printf(bio_err, "-rc2-64        encrypt with RC2-64\n");
        BIO_printf(bio_err, "-rc2-128       encrypt with RC2-128\n");
# endif
# ifndef OPENSSL_NO_AES
        BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
        BIO_printf(bio_err,
                   "               encrypt PEM output with cbc aes\n");
# endif
# ifndef OPENSSL_NO_CAMELLIA
        BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
        BIO_printf(bio_err,
                   "               encrypt PEM output with cbc camellia\n");
# endif
        BIO_printf(bio_err,
                   "-nointern      don't search certificates in message for signer\n");
        BIO_printf(bio_err,
                   "-nosigs        don't verify message signature\n");
        BIO_printf(bio_err,
                   "-noverify      don't verify signers certificate\n");
        BIO_printf(bio_err,
                   "-nocerts       don't include signers certificate when signing\n");
        BIO_printf(bio_err, "-nodetach      use opaque signing\n");
        BIO_printf(bio_err,
                   "-noattr        don't include any signed attributes\n");
        BIO_printf(bio_err,
                   "-binary        don't translate message to text\n");
        BIO_printf(bio_err, "-certfile file other certificates file\n");
        BIO_printf(bio_err, "-certsout file certificate output file\n");
        BIO_printf(bio_err, "-signer file   signer certificate file\n");
        BIO_printf(bio_err,
                   "-recip  file   recipient certificate file for decryption\n");
        BIO_printf(bio_err, "-keyid         use subject key identifier\n");
        BIO_printf(bio_err, "-in file       input file\n");
        BIO_printf(bio_err,
                   "-inform arg    input format SMIME (default), PEM or DER\n");
        BIO_printf(bio_err,
                   "-inkey file    input private key (if not signer or recipient)\n");
        BIO_printf(bio_err,
                   "-keyform arg   input private key format (PEM or ENGINE)\n");
        BIO_printf(bio_err, "-keyopt nm:v   set public key parameters\n");
        BIO_printf(bio_err, "-out file      output file\n");
        BIO_printf(bio_err,
                   "-outform arg   output format SMIME (default), PEM or DER\n");
        BIO_printf(bio_err,
                   "-content file  supply or override content for detached signature\n");
        BIO_printf(bio_err, "-to addr       to address\n");
        BIO_printf(bio_err, "-from ad       from address\n");
        BIO_printf(bio_err, "-subject s     subject\n");
        BIO_printf(bio_err,
                   "-text          include or delete text MIME headers\n");
        BIO_printf(bio_err,
                   "-CApath dir    trusted certificates directory\n");
        BIO_printf(bio_err, "-CAfile file   trusted certificates file\n");
        BIO_printf(bio_err,
                   "-crl_check     check revocation status of signer's certificate using CRLs\n");
        BIO_printf(bio_err,
                   "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
# ifndef OPENSSL_NO_ENGINE
        BIO_printf(bio_err,
                   "-engine e      use engine e, possibly a hardware device.\n");
# endif
        BIO_printf(bio_err, "-passin arg    input file pass phrase source\n");
        BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
                   LIST_SEPARATOR_CHAR);
        BIO_printf(bio_err,
                   "               load the file (or the files in the directory) into\n");
        BIO_printf(bio_err, "               the random number generator\n");
        BIO_printf(bio_err,
                   "cert.pem       recipient certificate(s) for encryption\n");
        goto end;
    }
# ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine, 0);
# endif

    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, bio_err, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~CMS_DETACHED;

    if (operation & SMIME_OP) {
        if (outformat == FORMAT_ASN1)
            outmode = "wb";
    } else {
        if (flags & CMS_BINARY)
            outmode = "wb";
    }

    if (operation & SMIME_IP) {
        if (informat == FORMAT_ASN1)
            inmode = "rb";
    } else {
        if (flags & CMS_BINARY)
            inmode = "rb";
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
# ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
# else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
# endif
        }

        if (secret_key && !secret_keyid) {
            BIO_printf(bio_err, "No secret key id\n");
            goto end;
        }

        if (*args && !encerts)
            encerts = sk_X509_new_null();
        while (*args) {
            if (!(cert = load_cert(bio_err, *args, FORMAT_PEM,
                                   NULL, e, "recipient certificate file")))
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            args++;
        }
    }

    if (certfile) {
        if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL,
                                 e, "certificate file"))) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL,
                                e, "recipient certificate file"))) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_SIGN_RECEIPT) {
        if (!(signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL,
                                 e, "receipt signer certificate file"))) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(bio_err, keyfile, keyform, 0, passin, e,
                       "signing key file");
        if (!key)
            goto end;
    }

    if (infile) {
        if (!(in = BIO_new_file(infile, inmode))) {
            BIO_printf(bio_err, "Can't open input file %s\n", infile);
            goto end;
        }
    } else
        in = BIO_new_fp(stdin, BIO_NOCLOSE);

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            cms = SMIME_read_CMS(in, &indata);
        else if (informat == FORMAT_PEM)
            cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            cms = d2i_CMS_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for CMS file\n");
            goto end;
        }

        if (!cms) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if (!(indata = BIO_new_file(contfile, "rb"))) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
        if (certsoutfile) {
            STACK_OF(X509) *allcerts;
            allcerts = CMS_get1_certs(cms);
            if (!save_certs(certsoutfile, allcerts)) {
                BIO_printf(bio_err,
                           "Error writing certs to %s\n", certsoutfile);
                ret = 5;
                goto end;
            }
            sk_X509_pop_free(allcerts, X509_free);
        }
    }

    if (rctfile) {
        char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
        if (!(rctin = BIO_new_file(rctfile, rctmode))) {
            BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
            goto end;
        }

        if (rctformat == FORMAT_SMIME)
            rcms = SMIME_read_CMS(rctin, NULL);
        else if (rctformat == FORMAT_PEM)
            rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
        else if (rctformat == FORMAT_ASN1)
            rcms = d2i_CMS_bio(rctin, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for receipt\n");
            goto end;
        }

        if (!rcms) {
            BIO_printf(bio_err, "Error reading receipt\n");
            goto end;
        }
    }

    if (outfile) {
        if (!(out = BIO_new_file(outfile, outmode))) {
            BIO_printf(bio_err, "Can't open output file %s\n", outfile);
            goto end;
        }
    } else {
        out = BIO_new_fp(stdout, BIO_NOCLOSE);
# ifdef OPENSSL_SYS_VMS
        {
            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
            out = BIO_push(tmpbio, out);
        }
# endif
    }

    if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
        if (!(store = setup_verify(bio_err, CAfile, CApath)))
            goto end;
        X509_STORE_set_verify_cb(store, cms_cb);
        if (vpm)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_DATA_CREATE) {
        cms = CMS_data_create(in, flags);
    } else if (operation == SMIME_DIGEST_CREATE) {
        cms = CMS_digest_create(in, sign_md, flags);
    } else if (operation == SMIME_COMPRESS) {
        cms = CMS_compress(in, -1, flags);
    } else if (operation == SMIME_ENCRYPT) {
        int i;
        flags |= CMS_PARTIAL;
        cms = CMS_encrypt(NULL, in, cipher, flags);
        if (!cms)
            goto end;
        for (i = 0; i < sk_X509_num(encerts); i++) {
            CMS_RecipientInfo *ri;
            cms_key_param *kparam;
            int tflags = flags;
            X509 *x = sk_X509_value(encerts, i);
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            ri = CMS_add1_recipient_cert(cms, x, tflags);
            if (!ri)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
                && wrap_cipher) {
                EVP_CIPHER_CTX *wctx;
                wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
                EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
            }
        }

        if (secret_key) {
            if (!CMS_add0_recipient_key(cms, NID_undef,
                                        secret_key, secret_keylen,
                                        secret_keyid, secret_keyidlen,
                                        NULL, NULL, NULL))
                goto end;
            /* NULL these because call absorbs them */
            secret_key = NULL;
            secret_keyid = NULL;
        }
        if (pwri_pass) {
            pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass);
            if (!pwri_tmp)
                goto end;
            if (!CMS_add0_recipient_password(cms,
                                             -1, NID_undef, NID_undef,
                                             pwri_tmp, -1, NULL))
                goto end;
            pwri_tmp = NULL;
        }
        if (!(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
        cms = CMS_EncryptedData_encrypt(in, cipher,
                                        secret_key, secret_keylen, flags);

    } else if (operation == SMIME_SIGN_RECEIPT) {
        CMS_ContentInfo *srcms = NULL;
        STACK_OF(CMS_SignerInfo) *sis;
        CMS_SignerInfo *si;
        sis = CMS_get0_SignerInfos(cms);
        if (!sis)
            goto end;
        si = sk_CMS_SignerInfo_value(sis, 0);
        srcms = CMS_sign_receipt(si, signer, key, other, flags);
        if (!srcms)
            goto end;
        CMS_ContentInfo_free(cms);
        cms = srcms;
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {

            if (flags & CMS_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= CMS_STREAM;
            }
            flags |= CMS_PARTIAL;
            cms = CMS_sign(NULL, NULL, other, in, flags);
            if (!cms)
                goto end;
            if (econtent_type)
                CMS_set1_eContentType(cms, econtent_type);

            if (rr_to) {
                rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
                if (!rr) {
                    BIO_puts(bio_err,
                             "Signed Receipt Request Creation Error\n");
                    goto end;
                }
            }
        } else
            flags |= CMS_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            CMS_SignerInfo *si;
            cms_key_param *kparam;
            int tflags = flags;
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);

            signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL,
                               e, "signer certificate");
            if (!signer)
                goto end;
            key = load_key(bio_err, keyfile, keyform, 0, passin, e,
                           "signing key file");
            if (!key)
                goto end;
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
            if (!si)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_SignerInfo_get0_pkey_ctx(si);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (rr && !CMS_add1_ReceiptRequest(si, rr))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    }

    if (!cms) {
        BIO_printf(bio_err, "Error creating CMS structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (flags & CMS_DEBUG_DECRYPT)
            CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);

        if (secret_key) {
            if (!CMS_decrypt_set1_key(cms,
                                      secret_key, secret_keylen,
                                      secret_keyid, secret_keyidlen)) {
                BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
                goto end;
            }
        }

        if (key) {
            if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
                BIO_puts(bio_err, "Error decrypting CMS using private key\n");
                goto end;
            }
        }

        if (pwri_pass) {
            if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
                BIO_puts(bio_err, "Error decrypting CMS using password\n");
                goto end;
            }
        }

        if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
            BIO_printf(bio_err, "Error decrypting CMS structure\n");
            goto end;
        }
    } else if (operation == SMIME_DATAOUT) {
        if (!CMS_data(cms, out, flags))
            goto end;
    } else if (operation == SMIME_UNCOMPRESS) {
        if (!CMS_uncompress(cms, indata, out, flags))
            goto end;
    } else if (operation == SMIME_DIGEST_VERIFY) {
        if (CMS_digest_verify(cms, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_DECRYPT) {
        if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
                                       indata, out, flags))
            goto end;
    } else if (operation == SMIME_VERIFY) {
        if (CMS_verify(cms, other, store, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            if (verify_retcode)
                ret = verify_err + 32;
            goto end;
        }
        if (signerfile) {
            STACK_OF(X509) *signers;
            signers = CMS_get0_signers(cms);
            if (!save_certs(signerfile, signers)) {
                BIO_printf(bio_err,
                           "Error writing signers to %s\n", signerfile);
                ret = 5;
                goto end;
            }
            sk_X509_free(signers);
        }
        if (rr_print)
            receipt_request_print(bio_err, cms);

    } else if (operation == SMIME_VERIFY_RECEIPT) {
        if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else {
        if (noout) {
            if (print)
                CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
        } else if (outformat == FORMAT_SMIME) {
            if (to)
                BIO_printf(out, "To: %s\n", to);
            if (from)
                BIO_printf(out, "From: %s\n", from);
            if (subject)
                BIO_printf(out, "Subject: %s\n", subject);
            if (operation == SMIME_RESIGN)
                ret = SMIME_write_CMS(out, cms, indata, flags);
            else
                ret = SMIME_write_CMS(out, cms, in, flags);
        } else if (outformat == FORMAT_PEM)
            ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
        else if (outformat == FORMAT_ASN1)
            ret = i2d_CMS_bio_stream(out, cms, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for CMS file\n");
            goto end;
        }
        if (ret <= 0) {
            ret = 6;
            goto end;
        }
    }
    ret = 0;
 end:
    if (ret)
        ERR_print_errors(bio_err);
    if (need_rand)
        app_RAND_write_file(NULL, bio_err);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    if (vpm)
        X509_VERIFY_PARAM_free(vpm);
    if (sksigners)
        sk_OPENSSL_STRING_free(sksigners);
    if (skkeys)
        sk_OPENSSL_STRING_free(skkeys);
    if (secret_key)
        OPENSSL_free(secret_key);
    if (secret_keyid)
        OPENSSL_free(secret_keyid);
    if (pwri_tmp)
        OPENSSL_free(pwri_tmp);
    if (econtent_type)
        ASN1_OBJECT_free(econtent_type);
    if (rr)
        CMS_ReceiptRequest_free(rr);
    if (rr_to)
        sk_OPENSSL_STRING_free(rr_to);
    if (rr_from)
        sk_OPENSSL_STRING_free(rr_from);
    for (key_param = key_first; key_param;) {
        cms_key_param *tparam;
        sk_OPENSSL_STRING_free(key_param->param);
        tparam = key_param->next;
        OPENSSL_free(key_param);
        key_param = tparam;
    }
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    CMS_ContentInfo_free(cms);
    CMS_ContentInfo_free(rcms);
    BIO_free(rctin);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    if (passin)
        OPENSSL_free(passin);
    return (ret);
}
示例#12
0
CERT *ssl_cert_dup(CERT *cert)
{
    CERT *ret = OPENSSL_zalloc(sizeof(*ret));
    int i;

    if (ret == NULL) {
        SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
        return (NULL);
    }

    ret->key = &ret->pkeys[cert->key - cert->pkeys];

#ifndef OPENSSL_NO_RSA
    if (cert->rsa_tmp != NULL) {
        RSA_up_ref(cert->rsa_tmp);
        ret->rsa_tmp = cert->rsa_tmp;
    }
    ret->rsa_tmp_cb = cert->rsa_tmp_cb;
#endif

#ifndef OPENSSL_NO_DH
    if (cert->dh_tmp != NULL) {
        ret->dh_tmp = DHparams_dup(cert->dh_tmp);
        if (ret->dh_tmp == NULL) {
            SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
            goto err;
        }
        if (cert->dh_tmp->priv_key) {
            BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
            if (!b) {
                SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
                goto err;
            }
            ret->dh_tmp->priv_key = b;
        }
        if (cert->dh_tmp->pub_key) {
            BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
            if (!b) {
                SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
                goto err;
            }
            ret->dh_tmp->pub_key = b;
        }
    }
    ret->dh_tmp_cb = cert->dh_tmp_cb;
    ret->dh_tmp_auto = cert->dh_tmp_auto;
#endif

#ifndef OPENSSL_NO_EC
    if (cert->ecdh_tmp) {
        ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
        if (ret->ecdh_tmp == NULL) {
            SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
            goto err;
        }
    }
    ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
    ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
#endif

    for (i = 0; i < SSL_PKEY_NUM; i++) {
        CERT_PKEY *cpk = cert->pkeys + i;
        CERT_PKEY *rpk = ret->pkeys + i;
        if (cpk->x509 != NULL) {
            rpk->x509 = cpk->x509;
            X509_up_ref(rpk->x509);
        }

        if (cpk->privatekey != NULL) {
            rpk->privatekey = cpk->privatekey;
            CRYPTO_add(&cpk->privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY);
        }

        if (cpk->chain) {
            rpk->chain = X509_chain_up_ref(cpk->chain);
            if (!rpk->chain) {
                SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }
        if (cert->pkeys[i].serverinfo != NULL) {
            /* Just copy everything. */
            ret->pkeys[i].serverinfo =
                OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
            if (ret->pkeys[i].serverinfo == NULL) {
                SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            ret->pkeys[i].serverinfo_length =
                cert->pkeys[i].serverinfo_length;
            memcpy(ret->pkeys[i].serverinfo,
                   cert->pkeys[i].serverinfo,
                   cert->pkeys[i].serverinfo_length);
        }
    }

    ret->references = 1;
    /* Configured sigalgs copied across */
    if (cert->conf_sigalgs) {
        ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
        if (!ret->conf_sigalgs)
            goto err;
        memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
        ret->conf_sigalgslen = cert->conf_sigalgslen;
    } else
        ret->conf_sigalgs = NULL;

    if (cert->client_sigalgs) {
        ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
        if (!ret->client_sigalgs)
            goto err;
        memcpy(ret->client_sigalgs, cert->client_sigalgs,
               cert->client_sigalgslen);
        ret->client_sigalgslen = cert->client_sigalgslen;
    } else
        ret->client_sigalgs = NULL;
    /* Shared sigalgs also NULL */
    ret->shared_sigalgs = NULL;
    /* Copy any custom client certificate types */
    if (cert->ctypes) {
        ret->ctypes = OPENSSL_malloc(cert->ctype_num);
        if (!ret->ctypes)
            goto err;
        memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
        ret->ctype_num = cert->ctype_num;
    }

    ret->cert_flags = cert->cert_flags;

    ret->cert_cb = cert->cert_cb;
    ret->cert_cb_arg = cert->cert_cb_arg;

    if (cert->verify_store) {
        CRYPTO_add(&cert->verify_store->references, 1,
                   CRYPTO_LOCK_X509_STORE);
        ret->verify_store = cert->verify_store;
    }

    if (cert->chain_store) {
        CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
        ret->chain_store = cert->chain_store;
    }

    ret->sec_cb = cert->sec_cb;
    ret->sec_level = cert->sec_level;
    ret->sec_ex = cert->sec_ex;

    if (!custom_exts_copy(&ret->cli_ext, &cert->cli_ext))
        goto err;
    if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
        goto err;

    if (cert->psk_identity_hint) {
        ret->psk_identity_hint = BUF_strdup(cert->psk_identity_hint);
        if (ret->psk_identity_hint == NULL)
            goto err;
    }

    return (ret);

 err:
    ssl_cert_free(ret);

    return NULL;
}
示例#13
0
static int/*bool*/
nss_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) {
    int ret = 0;
    NSS_CTX *ctx;

    CALL_TRACE("nss_ctrl() cmd=%d\n", cmd);

/* Put commands that do not require initialisation here*/
    switch (cmd) {
#ifdef CMD_SO_PATH
    case CMD_SO_PATH: {
        /* not implemented */;
        goto done;
        } break;
#endif
    }

/* Put commands that require initialisation here */
    if (nss_eng_ctx_index < 0) {
        NSSerr(NSS_F_CTRL, NSS_R_ENGINE_NOT_INITIALIZED);
        return(ret);
    }
    ctx = ENGINE_get_ex_data(e, nss_eng_ctx_index);

    switch (cmd) {
    case E_NSS_CMD_CONFIG_DIR: {
        ret = nss_cmd_nss_config_dir(ctx, (char*) p);
        } break;
    case E_NSS_CMD_DEBUG_LEVEL: {
        if (0 <= i && i <= NSS_LOGLEVEL_LAST) {
            ctx->debug_level = (int) i;
            ret = 1;
        }
        } break;
    case E_NSS_CMD_ERROR_FILE: {
        if (ctx->error_file != NULL)
            OPENSSL_free((void*)ctx->error_file);
        ctx->error_file = BUF_strdup(p);
        ret = 1;
        } break;
    case E_NSS_CMD_LIST_CERTS: {
        ret = nss_cmd_list_cert(ctx, i);
        } break;
    case E_NSS_CMD_PRINT_CERT: {
        ret = nss_cmd_print_cert(ctx, (char*) p);
        } break;
    case E_NSS_CMD_LOAD_CERT: {
        ret = nss_cmd_load_cert(ctx, p);
        } break;
    case E_NSS_CMD_EVP_CERT: {
        ret = nss_cmd_evp_cert(ctx, p);
        } break;
    default: {
        nss_trace(ctx, "nss_ctrl() <UNKNOWN=%d>\n", cmd);
        goto done;
        } break;
    }

done:
    return(ret);
}
示例#14
0
文件: connect.c 项目: RobinWuDev/Qt
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
  int *ip;
  const char **pptr;
  long ret = 1;
  BIO_CONNECT *data;

  data = (BIO_CONNECT *)bio->ptr;

  switch (cmd) {
    case BIO_CTRL_RESET:
      ret = 0;
      data->state = BIO_CONN_S_BEFORE;
      conn_close_socket(bio);
      bio->flags = 0;
      break;
    case BIO_C_DO_STATE_MACHINE:
      /* use this one to start the connection */
      if (data->state != BIO_CONN_S_OK)
        ret = (long)conn_state(bio, data);
      else
        ret = 1;
      break;
    case BIO_C_GET_CONNECT:
      /* TODO(fork): can this be removed? (Or maybe this whole file). */
      if (ptr != NULL) {
        pptr = (const char **)ptr;
        if (num == 0) {
          *pptr = data->param_hostname;
        } else if (num == 1) {
          *pptr = data->param_port;
        } else if (num == 2) {
          *pptr = (char *) &data->ip[0];
        } else if (num == 3) {
          *((int *)ptr) = data->port;
        }
        if (!bio->init) {
          *pptr = "not initialized";
        }
        ret = 1;
      }
      break;
    case BIO_C_SET_CONNECT:
      if (ptr != NULL) {
        bio->init = 1;
        if (num == 0) {
          if (data->param_hostname != NULL) {
            OPENSSL_free(data->param_hostname);
          }
          data->param_hostname = BUF_strdup(ptr);
        } else if (num == 1) {
          if (data->param_port != NULL) {
            OPENSSL_free(data->param_port);
          }
          data->param_port = BUF_strdup(ptr);
        } else {
          ret = 0;
        }
      }
      break;
    case BIO_C_SET_NBIO:
      data->nbio = (int)num;
      break;
    case BIO_C_GET_FD:
      if (bio->init) {
        ip = (int *)ptr;
        if (ip != NULL) {
          *ip = bio->num;
        }
        ret = 1;
      } else {
        ret = 0;
      }
      break;
    case BIO_CTRL_GET_CLOSE:
      ret = bio->shutdown;
      break;
    case BIO_CTRL_SET_CLOSE:
      bio->shutdown = (int)num;
      break;
    case BIO_CTRL_PENDING:
    case BIO_CTRL_WPENDING:
      ret = 0;
      break;
    case BIO_CTRL_FLUSH:
      break;
    case BIO_CTRL_SET_CALLBACK: {
#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
		OPENSSL_PUT_ERROR(BIO, XXX, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
		ret = -1;
#else
      ret = 0;
#endif
    } break;
    case BIO_CTRL_GET_CALLBACK: {
      int (**fptr)(const BIO *bio, int state, int xret);
      fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
      *fptr = data->info_callback;
    } break;
    default:
      ret = 0;
      break;
  }
  return (ret);
}
示例#15
0
int SSL_SRP_CTX_init(struct ssl_st *s)
	{
	SSL_CTX *ctx;

	if ((s == NULL) || ((ctx = s->ctx) == NULL))
		return 0;
	s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
	/* set client Hello login callback */
	s->srp_ctx.TLS_ext_srp_username_callback = ctx->srp_ctx.TLS_ext_srp_username_callback;
	/* set SRP N/g param callback for verification */
	s->srp_ctx.SRP_verify_param_callback = ctx->srp_ctx.SRP_verify_param_callback;
	/* set SRP client passwd callback */
	s->srp_ctx.SRP_give_srp_client_pwd_callback = ctx->srp_ctx.SRP_give_srp_client_pwd_callback;

	s->srp_ctx.N = NULL;
	s->srp_ctx.g = NULL;
	s->srp_ctx.s = NULL;
	s->srp_ctx.B = NULL;
	s->srp_ctx.A = NULL;
	s->srp_ctx.a = NULL;
	s->srp_ctx.b = NULL;
	s->srp_ctx.v = NULL;
	s->srp_ctx.login = NULL;
	s->srp_ctx.info = ctx->srp_ctx.info;
	s->srp_ctx.strength = ctx->srp_ctx.strength;

	if (((ctx->srp_ctx.N != NULL) &&
		 ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
		((ctx->srp_ctx.g != NULL) &&
		 ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
		((ctx->srp_ctx.s != NULL) &&
		 ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
		((ctx->srp_ctx.B != NULL) &&
		 ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
		((ctx->srp_ctx.A != NULL) &&
		 ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
		((ctx->srp_ctx.a != NULL) &&
		 ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
		((ctx->srp_ctx.v != NULL) &&
		 ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
		((ctx->srp_ctx.b != NULL) &&
		 ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL)))
		{
		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_BN_LIB);
		goto err;
		}
	if ((ctx->srp_ctx.login != NULL) && 
		((s->srp_ctx.login = BUF_strdup(ctx->srp_ctx.login)) == NULL))
		{
		SSLerr(SSL_F_SSL_SRP_CTX_INIT,ERR_R_INTERNAL_ERROR);
		goto err;
		}
	s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;

	return (1);
err:
	OPENSSL_free(s->srp_ctx.login);
	BN_free(s->srp_ctx.N);
	BN_free(s->srp_ctx.g);
	BN_free(s->srp_ctx.s);
	BN_free(s->srp_ctx.B);
	BN_free(s->srp_ctx.A);
	BN_free(s->srp_ctx.a);
	BN_free(s->srp_ctx.b);
	BN_free(s->srp_ctx.v);
	return (0);
	}
示例#16
0
static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
	{
	BIO *dbio;
	int *ip;
	const char **pptr;
	long ret=1;
	BIO_CONNECT *data;

	data=(BIO_CONNECT *)b->ptr;

	switch (cmd)
		{
	case BIO_CTRL_RESET:
		ret=0;
		data->state=BIO_CONN_S_BEFORE;
		conn_close_socket(b);
		b->flags=0;
		break;
	case BIO_C_DO_STATE_MACHINE:
		/* use this one to start the connection */
		if (!data->state != BIO_CONN_S_OK)
			ret=(long)conn_state(b,data);
		else
			ret=1;
		break;
	case BIO_C_GET_CONNECT:
		if (ptr != NULL)
			{
			pptr=(const char **)ptr;
			if (num == 0)
				{
				*pptr=data->param_hostname;

				}
			else if (num == 1)
				{
				*pptr=data->param_port;
				}
			else if (num == 2)
				{
				*pptr= (char *)&(data->ip[0]);
				}
			else if (num == 3)
				{
				*((int *)ptr)=data->port;
				}
			if ((!b->init) || (ptr == NULL))
				*pptr="not initialized";
			ret=1;
			}
		break;
	case BIO_C_SET_CONNECT:
		if (ptr != NULL)
			{
			b->init=1;
			if (num == 0)
				{
				if (data->param_hostname != NULL)
					OPENSSL_free(data->param_hostname);
				data->param_hostname=BUF_strdup(ptr);
				}
			else if (num == 1)
				{
				if (data->param_port != NULL)
					OPENSSL_free(data->param_port);
				data->param_port=BUF_strdup(ptr);
				}
			else if (num == 2)
				{
				char buf[16];
				unsigned char *p = ptr;

				BIO_snprintf(buf,sizeof buf,"%d.%d.%d.%d",
					     p[0],p[1],p[2],p[3]);
				if (data->param_hostname != NULL)
					OPENSSL_free(data->param_hostname);
				data->param_hostname=BUF_strdup(buf);
				memcpy(&(data->ip[0]),ptr,4);
				}
			else if (num == 3)
				{
				char buf[DECIMAL_SIZE(int)+1];

				BIO_snprintf(buf,sizeof buf,"%d",*(int *)ptr);
				if (data->param_port != NULL)
					OPENSSL_free(data->param_port);
				data->param_port=BUF_strdup(buf);
				data->port= *(int *)ptr;
				}
			}
		break;
	case BIO_C_SET_NBIO:
		data->nbio=(int)num;
		break;
	case BIO_C_GET_FD:
		if (b->init)
			{
			ip=(int *)ptr;
			if (ip != NULL)
				*ip=b->num;
			ret=b->num;
			}
		else
			ret= -1;
		break;
	case BIO_CTRL_GET_CLOSE:
		ret=b->shutdown;
		break;
	case BIO_CTRL_SET_CLOSE:
		b->shutdown=(int)num;
		break;
	case BIO_CTRL_PENDING:
	case BIO_CTRL_WPENDING:
		ret=0;
		break;
	case BIO_CTRL_FLUSH:
		break;
	case BIO_CTRL_DUP:
		{
		dbio=(BIO *)ptr;
		if (data->param_port)
			BIO_set_conn_port(dbio,data->param_port);
		if (data->param_hostname)
			BIO_set_conn_hostname(dbio,data->param_hostname);
		BIO_set_nbio(dbio,data->nbio);
		/* FIXME: the cast of the function seems unlikely to be a good idea */
                (void)BIO_set_info_callback(dbio,(bio_info_cb *)data->info_callback);
		}
		break;
	case BIO_CTRL_SET_CALLBACK:
		{
#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
		BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
		ret = -1;
#else
		ret=0;
#endif
		}
		break;
	case BIO_CTRL_GET_CALLBACK:
		{
		int (**fptr)();

		fptr=(int (**)())ptr;
		*fptr=data->info_callback;
		}
		break;
	default:
		ret=0;
		break;
		}
	return(ret);
	}
示例#17
0
文件: eng_dyn.c 项目: shrug/openssl
static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
{
    dynamic_data_ctx *ctx = dynamic_get_data_ctx(e);
    int initialised;

    if (!ctx) {
        ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED);
        return 0;
    }
    initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
    /* All our control commands require the ENGINE to be uninitialised */
    if (initialised) {
        ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED);
        return 0;
    }
    switch (cmd) {
    case DYNAMIC_CMD_SO_PATH:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (p && (strlen((const char *)p) < 1))
            p = NULL;
        OPENSSL_free(ctx->DYNAMIC_LIBNAME);
        if (p)
            ctx->DYNAMIC_LIBNAME = BUF_strdup(p);
        else
            ctx->DYNAMIC_LIBNAME = NULL;
        return (ctx->DYNAMIC_LIBNAME ? 1 : 0);
    case DYNAMIC_CMD_NO_VCHECK:
        ctx->no_vcheck = ((i == 0) ? 0 : 1);
        return 1;
    case DYNAMIC_CMD_ID:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (p && (strlen((const char *)p) < 1))
            p = NULL;
        OPENSSL_free(ctx->engine_id);
        if (p)
            ctx->engine_id = BUF_strdup(p);
        else
            ctx->engine_id = NULL;
        return (ctx->engine_id ? 1 : 0);
    case DYNAMIC_CMD_LIST_ADD:
        if ((i < 0) || (i > 2)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        ctx->list_add_value = (int)i;
        return 1;
    case DYNAMIC_CMD_LOAD:
        return dynamic_load(e, ctx);
    case DYNAMIC_CMD_DIR_LOAD:
        if ((i < 0) || (i > 2)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        ctx->dir_load = (int)i;
        return 1;
    case DYNAMIC_CMD_DIR_ADD:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (!p || (strlen((const char *)p) < 1)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        {
            char *tmp_str = BUF_strdup(p);
            if (!tmp_str) {
                ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
                return 0;
            }
            sk_OPENSSL_STRING_insert(ctx->dirs, tmp_str, -1);
        }
        return 1;
    default:
        break;
    }
    ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
    return 0;
}
示例#18
0
int ssl_get_new_session(SSL *s, int session) {
  /* This gets used by clients and servers. */

  unsigned int tmp;
  SSL_SESSION *ss = NULL;
  GEN_SESSION_CB cb = def_generate_session_id;

  if (s->mode & SSL_MODE_NO_SESSION_CREATION) {
    OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
                      SSL_R_SESSION_MAY_NOT_BE_CREATED);
    return 0;
  }

  ss = SSL_SESSION_new();
  if (ss == NULL) {
    return 0;
  }

  /* If the context has a default timeout, use it over the default. */
  if (s->initial_ctx->session_timeout != 0) {
    ss->timeout = s->initial_ctx->session_timeout;
  }

  if (s->session != NULL) {
    SSL_SESSION_free(s->session);
    s->session = NULL;
  }

  if (session) {
    if (s->version == SSL3_VERSION || s->version == TLS1_VERSION ||
        s->version == TLS1_1_VERSION || s->version == TLS1_2_VERSION ||
        s->version == DTLS1_VERSION || s->version == DTLS1_2_VERSION) {
      ss->ssl_version = s->version;
      ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
    } else {
      OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
                        SSL_R_UNSUPPORTED_SSL_VERSION);
      SSL_SESSION_free(ss);
      return 0;
    }

    /* If RFC4507 ticket use empty session ID */
    if (s->tlsext_ticket_expected) {
      ss->session_id_length = 0;
      goto sess_id_done;
    }

    /* Choose which callback will set the session ID */
    CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
    if (s->generate_session_id) {
      cb = s->generate_session_id;
    } else if (s->initial_ctx->generate_session_id) {
      cb = s->initial_ctx->generate_session_id;
    }
    CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);

    /* Choose a session ID */
    tmp = ss->session_id_length;
    if (!cb(s, ss->session_id, &tmp)) {
      /* The callback failed */
      OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
                        SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
      SSL_SESSION_free(ss);
      return 0;
    }

    /* Don't allow the callback to set the session length to zero. nor set it
     * higher than it was. */
    if (!tmp || tmp > ss->session_id_length) {
      /* The callback set an illegal length */
      OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
                        SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
      SSL_SESSION_free(ss);
      return 0;
    }

    ss->session_id_length = tmp;
    /* Finally, check for a conflict */
    if (SSL_has_matching_session_id(s, ss->session_id, ss->session_id_length)) {
      OPENSSL_PUT_ERROR(SSL, ssl_get_new_session,
                        SSL_R_SSL_SESSION_ID_CONFLICT);
      SSL_SESSION_free(ss);
      return 0;
    }

  sess_id_done:
    if (s->tlsext_hostname) {
      ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
      if (ss->tlsext_hostname == NULL) {
        OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR);
        SSL_SESSION_free(ss);
        return 0;
      }
    }
  } else {
    ss->session_id_length = 0;
  }

  if (s->sid_ctx_length > sizeof(ss->sid_ctx)) {
    OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR);
    SSL_SESSION_free(ss);
    return 0;
  }

  memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length);
  ss->sid_ctx_length = s->sid_ctx_length;
  s->session = ss;
  ss->ssl_version = s->version;
  ss->verify_result = X509_V_OK;

  return 1;
}
示例#19
0
int X509_PURPOSE_add(int id, int trust, int flags,
			int (*ck)(const X509_PURPOSE *, const X509 *, int),
					char *name, char *sname, void *arg)
{
	int idx;
	X509_PURPOSE *ptmp;
	char *name_dup, *sname_dup;

	/* This is set according to what we change: application can't set it */
	flags &= ~X509_PURPOSE_DYNAMIC;
	/* This will always be set for application modified trust entries */
	flags |= X509_PURPOSE_DYNAMIC_NAME;
	/* Get existing entry if any */
	idx = X509_PURPOSE_get_by_id(id);
	/* Need a new entry */
	if(idx == -1) {
		if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
			OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
			return 0;
		}
		ptmp->flags = X509_PURPOSE_DYNAMIC;
	} else ptmp = X509_PURPOSE_get0(idx);

	/* Duplicate the supplied names. */
	name_dup = BUF_strdup(name);
	sname_dup = BUF_strdup(sname);
	if (name_dup == NULL || sname_dup == NULL) {
		OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
		if (name_dup != NULL)
			OPENSSL_free(name_dup);
		if (sname_dup != NULL)
			OPENSSL_free(sname_dup);
		if (idx == -1)
			OPENSSL_free(ptmp);
		return 0;
	}

	/* OPENSSL_free existing name if dynamic */
	if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
		OPENSSL_free(ptmp->name);
		OPENSSL_free(ptmp->sname);
	}
	/* dup supplied name */
	ptmp->name = name_dup;
	ptmp->sname = sname_dup;
	/* Keep the dynamic flag of existing entry */
	ptmp->flags &= X509_PURPOSE_DYNAMIC;
	/* Set all other flags */
	ptmp->flags |= flags;

	ptmp->purpose = id;
	ptmp->trust = trust;
	ptmp->check_purpose = ck;
	ptmp->usr_data = arg;

	/* If its a new entry manage the dynamic table */
	if(idx == -1) {
		if(!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
			OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
			xptable_free(ptmp);
			return 0;
		}
		if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
			OPENSSL_PUT_ERROR(X509V3, X509_PURPOSE_add, ERR_R_MALLOC_FAILURE);
			xptable_free(ptmp);
			return 0;
		}
	}
	return 1;
}
示例#20
0
文件: srp.c 项目: 2wce/Signal-Android
int MAIN(int argc, char **argv)
{
    int add_user = 0;
    int list_user= 0;
    int delete_user= 0;
    int modify_user= 0;
    char * user = NULL;

    char *passargin = NULL, *passargout = NULL;
    char *passin = NULL, *passout = NULL;
    char * gN = NULL;
    int gNindex = -1;
    char ** gNrow = NULL;
    int maxgN = -1;

    char * userinfo = NULL;

    int badops=0;
    int ret=1;
    int errors=0;
    int verbose=0;
    int doupdatedb=0;
    char *configfile=NULL;
    char *dbfile=NULL;
    CA_DB *db=NULL;
    char **pp ;
    int i;
    long errorline = -1;
    char *randfile=NULL;
#ifndef OPENSSL_NO_ENGINE
    char *engine = NULL;
#endif
    char *tofree=NULL;
    DB_ATTR db_attr;

#ifdef EFENCE
    EF_PROTECT_FREE=1;
    EF_PROTECT_BELOW=1;
    EF_ALIGNMENT=0;
#endif

    apps_startup();

    conf = NULL;
    section = NULL;

    if (bio_err == NULL)
        if ((bio_err=BIO_new(BIO_s_file())) != NULL)
            BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

    argc--;
    argv++;
    while (argc >= 1 && badops == 0)
    {
        if	(strcmp(*argv,"-verbose") == 0)
            verbose++;
        else if	(strcmp(*argv,"-config") == 0)
        {
            if (--argc < 1) goto bad;
            configfile= *(++argv);
        }
        else if (strcmp(*argv,"-name") == 0)
        {
            if (--argc < 1) goto bad;
            section= *(++argv);
        }
        else if	(strcmp(*argv,"-srpvfile") == 0)
        {
            if (--argc < 1) goto bad;
            dbfile= *(++argv);
        }
        else if (strcmp(*argv,"-add") == 0)
            add_user=1;
        else if (strcmp(*argv,"-delete") == 0)
            delete_user=1;
        else if (strcmp(*argv,"-modify") == 0)
            modify_user=1;
        else if (strcmp(*argv,"-list") == 0)
            list_user=1;
        else if (strcmp(*argv,"-gn") == 0)
        {
            if (--argc < 1) goto bad;
            gN= *(++argv);
        }
        else if (strcmp(*argv,"-userinfo") == 0)
        {
            if (--argc < 1) goto bad;
            userinfo= *(++argv);
        }
        else if (strcmp(*argv,"-passin") == 0)
        {
            if (--argc < 1) goto bad;
            passargin= *(++argv);
        }
        else if (strcmp(*argv,"-passout") == 0)
        {
            if (--argc < 1) goto bad;
            passargout= *(++argv);
        }
#ifndef OPENSSL_NO_ENGINE
        else if (strcmp(*argv,"-engine") == 0)
        {
            if (--argc < 1) goto bad;
            engine= *(++argv);
        }
#endif

        else if (**argv == '-')
        {
bad:
            BIO_printf(bio_err,"unknown option %s\n",*argv);
            badops=1;
            break;
        }
        else
            break;

        argc--;
        argv++;
    }

    if (dbfile && configfile)
    {
        BIO_printf(bio_err,"-dbfile and -configfile cannot be specified together.\n");
        badops = 1;
    }
    if (add_user+delete_user+modify_user+list_user != 1)
    {
        BIO_printf(bio_err,"Exactly one of the options -add, -delete, -modify -list must be specified.\n");
        badops = 1;
    }
    if (delete_user+modify_user+delete_user== 1 && argc <= 0)
    {
        BIO_printf(bio_err,"Need at least one user for options -add, -delete, -modify. \n");
        badops = 1;
    }
    if ((passin || passout) && argc != 1 )
    {
        BIO_printf(bio_err,"-passin, -passout arguments only valid with one user.\n");
        badops = 1;
    }

    if (badops)
    {
        for (pp=srp_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err,"%s",*pp);

        BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
        BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
        BIO_printf(bio_err,"                 the random number generator\n");
        goto err;
    }

    ERR_load_crypto_strings();

#ifndef OPENSSL_NO_ENGINE
    setup_engine(bio_err, engine, 0);
#endif

    if(!app_passwd(bio_err, passargin, passargout, &passin, &passout))
    {
        BIO_printf(bio_err, "Error getting passwords\n");
        goto err;
    }

    if (!dbfile)
    {


        /*****************************************************************/
        tofree=NULL;
        if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
        if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
        if (configfile == NULL)
        {
            const char *s=X509_get_default_cert_area();
            size_t len;

#ifdef OPENSSL_SYS_VMS
            len = strlen(s)+sizeof(CONFIG_FILE);
            tofree=OPENSSL_malloc(len);
            strcpy(tofree,s);
#else
            len = strlen(s)+sizeof(CONFIG_FILE)+1;
            tofree=OPENSSL_malloc(len);
            BUF_strlcpy(tofree,s,len);
            BUF_strlcat(tofree,"/",len);
#endif
            BUF_strlcat(tofree,CONFIG_FILE,len);
            configfile=tofree;
        }

        VERBOSE BIO_printf(bio_err,"Using configuration from %s\n",configfile);
        conf = NCONF_new(NULL);
        if (NCONF_load(conf,configfile,&errorline) <= 0)
        {
            if (errorline <= 0)
                BIO_printf(bio_err,"error loading the config file '%s'\n",
                           configfile);
            else
                BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
                           ,errorline,configfile);
            goto err;
        }
        if(tofree)
        {
            OPENSSL_free(tofree);
            tofree = NULL;
        }

        if (!load_config(bio_err, conf))
            goto err;

        /* Lets get the config section we are using */
        if (section == NULL)
        {
            VERBOSE BIO_printf(bio_err,"trying to read " ENV_DEFAULT_SRP " in \" BASE_SECTION \"\n");

            section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_SRP);
            if (section == NULL)
            {
                lookup_fail(BASE_SECTION,ENV_DEFAULT_SRP);
                goto err;
            }
        }

        if (randfile == NULL && conf)
            randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");


        VERBOSE BIO_printf(bio_err,"trying to read " ENV_DATABASE " in section \"%s\"\n",section);

        if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
        {
            lookup_fail(section,ENV_DATABASE);
            goto err;
        }

    }
    if (randfile == NULL)
        ERR_clear_error();
    else
        app_RAND_load_file(randfile, bio_err, 0);

    VERBOSE BIO_printf(bio_err,"Trying to read SRP verifier file \"%s\"\n",dbfile);

    db = load_index(dbfile, &db_attr);
    if (db == NULL) goto err;

    /* Lets check some fields */
    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
    {
        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);

        if (pp[DB_srptype][0] == DB_SRP_INDEX)
        {
            maxgN = i;
            if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid]))
                gNindex = i;

            print_index(db, bio_err, i, verbose > 1);
        }
    }

    VERBOSE BIO_printf(bio_err, "Database initialised\n");

    if (gNindex >= 0)
    {
        gNrow = sk_OPENSSL_PSTRING_value(db->db->data,gNindex);
        print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N");
    }
    else if (maxgN > 0 && !SRP_get_default_gN(gN))
    {
        BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
        goto err;
    }
    else
    {
        VERBOSE BIO_printf(bio_err, "Database has no g N information.\n");
        gNrow = NULL;
    }


    VVERBOSE BIO_printf(bio_err,"Starting user processing\n");

    if (argc > 0)
        user = *(argv++) ;

    while (list_user || user)
    {
        int userindex = -1;
        if (user)
            VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user);
        if ((userindex = get_index(db, user, 'U')) >= 0)
        {
            print_user(db, bio_err, userindex, (verbose > 0) || list_user);
        }

        if (list_user)
        {
            if (user == NULL)
            {
                BIO_printf(bio_err,"List all users\n");

                for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
                {
                    print_user(db,bio_err, i, 1);
                }
                list_user = 0;
            }
            else if (userindex < 0)
            {
                BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n",
                           user);
                errors++;
            }
        }
        else if (add_user)
        {
            if (userindex >= 0)
            {
                /* reactivation of a new user */
                char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
                BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
                row[DB_srptype][0] = 'V';

                doupdatedb = 1;
            }
            else
            {
                char *row[DB_NUMBER] ;
                char *gNid;
                row[DB_srpverifier] = NULL;
                row[DB_srpsalt] = NULL;
                row[DB_srpinfo] = NULL;
                if (!(gNid = srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:gN,gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
                {
                    BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user);
                    errors++;
                    goto err;
                }
                row[DB_srpid] = BUF_strdup(user);
                row[DB_srptype] = BUF_strdup("v");
                row[DB_srpgN] = BUF_strdup(gNid);

                if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
                        (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))) ||
                        !update_index(db, bio_err, row))
                {
                    if (row[DB_srpid]) OPENSSL_free(row[DB_srpid]);
                    if (row[DB_srpgN]) OPENSSL_free(row[DB_srpgN]);
                    if (row[DB_srpinfo]) OPENSSL_free(row[DB_srpinfo]);
                    if (row[DB_srptype]) OPENSSL_free(row[DB_srptype]);
                    if (row[DB_srpverifier]) OPENSSL_free(row[DB_srpverifier]);
                    if (row[DB_srpsalt]) OPENSSL_free(row[DB_srpsalt]);
                    goto err;
                }
                doupdatedb = 1;
            }
        }
        else if (modify_user)
        {
            if (userindex < 0)
            {
                BIO_printf(bio_err,"user \"%s\" does not exist, operation ignored.\n",user);
                errors++;
            }
            else
            {

                char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex);
                char type = row[DB_srptype][0];
                if (type == 'v')
                {
                    BIO_printf(bio_err,"user \"%s\" already updated, operation ignored.\n",user);
                    errors++;
                }
                else
                {
                    char *gNid;

                    if (row[DB_srptype][0] == 'V')
                    {
                        int user_gN;
                        char **irow = NULL;
                        VERBOSE BIO_printf(bio_err,"Verifying password for user \"%s\"\n",user);
                        if ( (user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
                            irow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);

                        if (!srp_verify_user(user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, bio_err, verbose))
                        {
                            BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user);
                            errors++;
                            goto err;
                        }
                    }
                    VERBOSE BIO_printf(bio_err,"Password for user \"%s\" ok.\n",user);

                    if (!(gNid=srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:NULL, gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
                    {
                        BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user);
                        errors++;
                        goto err;
                    }

                    row[DB_srptype][0] = 'v';
                    row[DB_srpgN] = BUF_strdup(gNid);

                    if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
                            (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))))
                        goto err;

                    doupdatedb = 1;
                }
            }
        }
        else if (delete_user)
        {
            if (userindex < 0)
            {
                BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user);
                errors++;
            }
            else
            {
                char **xpp = sk_OPENSSL_PSTRING_value(db->db->data,userindex);
                BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);

                xpp[DB_srptype][0] = 'R';

                doupdatedb = 1;
            }
        }
        if (--argc > 0)
            user = *(argv++) ;
        else
        {
            user = NULL;
            list_user = 0;
        }
    }

    VERBOSE BIO_printf(bio_err,"User procession done.\n");


    if (doupdatedb)
    {
        /* Lets check some fields */
        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
        {
            pp = sk_OPENSSL_PSTRING_value(db->db->data,i);

            if (pp[DB_srptype][0] == 'v')
            {
                pp[DB_srptype][0] = 'V';
                print_user(db, bio_err, i, verbose);
            }
        }

        VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n");
        if (!save_index(dbfile, "new", db)) goto err;

        VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n");
        if (!rotate_index(dbfile, "new", "old")) goto err;

        VERBOSE BIO_printf(bio_err, "srpvfile updated.\n");
    }

    ret = (errors != 0);
err:
    if (errors != 0)
        VERBOSE BIO_printf(bio_err,"User errors %d.\n",errors);

    VERBOSE BIO_printf(bio_err,"SRP terminating with code %d.\n",ret);
    if(tofree)
        OPENSSL_free(tofree);
    if (ret) ERR_print_errors(bio_err);
    if (randfile) app_RAND_write_file(randfile, bio_err);
    if (conf) NCONF_free(conf);
    if (db) free_index(db);

    OBJ_cleanup();
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
static long set_CSWIFT_LIBNAME(const char *name)
	{
	free_CSWIFT_LIBNAME();
	return (((CSWIFT_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
示例#22
0
int file_select(const struct dirent *entry) {
         cert                        = X509_new();
         certsubject                 = X509_NAME_new();
	 int i                       = 0;
	 char buf[80]                = "";

  /* check for "." and ".." directory entries */
  if(entry->d_name[0]=='.') return 0;

  /* Check for <id>.pem file name extensions */
  if(strstr(entry->d_name, ".pem") == NULL) return 0;

  /* generate the full file name and path to open it */
  snprintf(certfilestr, sizeof(certfilestr), "%s/%s",
                           CACERTSTORE, entry->d_name);

  /* if we cannot open the file, we move on  to the next */
  if ((certfile = fopen(certfilestr, "r")) == NULL) return 0;

  /* now we load the certificate data */
  if (! (cert = PEM_read_X509(certfile,NULL,NULL,NULL))) return 0;

  /* if search type is dn, check if dn field contains the search value */
  if (strcmp(search, "dn") == 0) {

    /* get the subject information to compare the entries in it */
    if (! (certsubject = X509_get_subject_name(cert))) return 0;

    /* now we cycle through all entries of the subject */
    for (i = 0; i < X509_NAME_entry_count(certsubject); i++) {
      e = X509_NAME_get_entry(certsubject, i);
      OBJ_obj2txt(buf, 80, X509_NAME_ENTRY_get_object(e), 0);

      /* when the search file matches the cert subject field  */
      /* check if the field value is equal the search value   */
      if(strstr(buf, field) != NULL)
        if(strstr( (char *) X509_NAME_ENTRY_get_data(e), dnvalue) != NULL) return 1;
    }
  }

  /* if search type is exp, check expiration date is between start and end date */
  if (strcmp(search, "exp") == 0) {

    /* get the certificates expiration date */
    expiration_date = X509_get_notAfter(cert);

    /* copy the certificate expiration date into a string */
    membio = BIO_new(BIO_s_mem());
    ASN1_TIME_print(membio, expiration_date);
    BIO_gets(membio, membio_buf, sizeof(membio_buf));
    BIO_free(membio);
    //int_error(membio_buf); /* debug correct time parsing */

    /* parse the expiration date string into a time struct */
    memset (&expiration_tm, '\0', sizeof(expiration_tm));
    strptime(membio_buf, "%h %d %T %Y %z", &expiration_tm);
    // int_error(asctime(&expiration_tm)); /* debug correct time parsing */

    /* parse the CGI start date string into the start_tm struct */
    memset (&start_tm, '\0', sizeof(start_tm));
    strptime(exp_startstr, "%d.%m.%Y %R", &start_tm);
    // int_error(asctime(&start_tm)); /* debug correct time parsing */

    /* parse the CGI end date string into the end_tm struct */
    memset (&end_tm, '\0', sizeof(end_tm));
    strptime(exp_endstr, "%d.%m.%Y %R", &end_tm);
    // int_error(asctime(&end_tm)); /* debug correct time parsing */

    /* check if expiration date >= start date and <= end date */
    if ( difftime(mktime(&start_tm), mktime(&expiration_tm)) <=0 &&
         difftime(mktime(&end_tm), mktime(&expiration_tm)) >= 0 ) return 1;
  }
  /* if search type is ena, check enable date is between start and end date */
  if (strcmp(search, "ena") == 0) {

    /* get the certificates enable date */
    start_date = X509_get_notBefore(cert);

    /* copy the certificate expiration date into a string */
    membio = BIO_new(BIO_s_mem());
    ASN1_TIME_print(membio, start_date);
    BIO_gets(membio, membio_buf, sizeof(membio_buf));
    BIO_free(membio);

    /* parse the expiration date string into a time struct */
    memset (&enable_tm, '\0', sizeof(enable_tm));
    strptime(membio_buf, "%h %d %T %Y %z", &enable_tm);
    // int_error(asctime(&enable_tm)); /* debug correct time parsing */

    /* parse the CGI start date string into the start_tm struct */
    memset (&start_tm, '\0', sizeof(start_tm));
    strptime(ena_startstr, "%d.%m.%Y %R", &start_tm);
    // int_error(asctime(&start_tm)); /* debug correct time parsing */

    /* parse the CGI end date string into the end_tm struct */
    memset (&end_tm, '\0', sizeof(end_tm));
    strptime(ena_endstr, "%d.%m.%Y %R", &end_tm);
    // int_error(asctime(&end_tm)); /* debug correct time parsing */

    /* check if expiration date >= start date and <= end date */
    if ( difftime(mktime(&start_tm), mktime(&enable_tm)) <=0 &&
         difftime(mktime(&end_tm), mktime(&enable_tm)) >= 0 ) return 1;
  }
  /* if search type is rev, check if cert was revoked between start and end date */
  if (strcmp(search, "rev") == 0) {
    /* ---------------------------------------------------------- *
     * Parse the CGI start date string into the start_tm struct   *
     * ---------------------------------------------------------- */
    memset (&start_tm, '\0', sizeof(start_tm));
    strptime(rev_startstr, "%d.%m.%Y %R", &start_tm);
    /* ---------------------------------------------------------- *
     * Parse the CGI end date string into the end_tm struct       *
     * ---------------------------------------------------------- */
    memset (&end_tm, '\0', sizeof(end_tm));
    strptime(rev_endstr, "%d.%m.%Y %R", &end_tm);
    /* ---------------------------------------------------------- *
     * Get all revoked certificates from revocation DB index.txt  *
     * ---------------------------------------------------------- */
    CA_DB *db = NULL;
    DB_ATTR db_attr;

    if((db = load_index(INDEXFILE, &db_attr)) == NULL)
      int_error("Error cannot load CRL certificate database file");

    /* ---------------------------------------------------------- *
     * Get the certs serial number, convert it into a hex string  *
     * -----------------------------------------------------------*/
    BIGNUM *bn = NULL;
    bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
    if (!bn)
     int_error("Cannot extract serial number from cert into BIGNUM");
    char *serialstr = BN_bn2hex(bn);

    /* ---------------------------------------------------------- *
     * Check if the cert is revoked, looking up its serial in DB  *
     * -----------------------------------------------------------*/
    char *const *pp;
    int i;
    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
      pp = sk_OPENSSL_PSTRING_value(db->db->data, i);

      if ( (strcmp(pp[DB_serial], serialstr) == 0)
           && (pp[DB_type][0] == DB_TYPE_REV) )  {

        /* ---------------------------------------------------------- *
         * Revoked, get the certs revocation date from the database   *
         * -----------------------------------------------------------*/
        char *p = strchr(pp[DB_rev_date], ',');
        if (p) *p = '\0'; // if revocation reason is given, terminate before 
        char *revokedstr = BUF_strdup(pp[DB_rev_date]);
        revocation_date = ASN1_UTCTIME_new();
        ASN1_UTCTIME_set_string(revocation_date, revokedstr);
        //int_error(revokedstr); /* debug correct time parsing */

        /* copy the certificate revocation date into a string */
        membio = BIO_new(BIO_s_mem());
        ASN1_TIME_print(membio, revocation_date);
        BIO_gets(membio, membio_buf, sizeof(membio_buf));
        BIO_free(membio);
        //int_error(membio_buf);

        /* parse the revocation date string into a time struct */
        memset (&revoked_tm, '\0', sizeof(revoked_tm));
        strptime(membio_buf, "%h %d %T %Y %z", &revoked_tm);
        //int_error(asctime(&revoked_tm)); /* debug correct time parsing */

        /* ---------------------------------------------------------- *
         * Check if revocation date >= start date and <= end date     *
         * -----------------------------------------------------------*/
        if ( difftime(mktime(&start_tm), mktime(&revoked_tm)) <=0 &&
             difftime(mktime(&end_tm), mktime(&revoked_tm)) >= 0 ) return 1;
      }
    }
    BN_free(bn);
  }
  /* if search type is ser, check if serial is between start and end serial */
  if (strcmp(search, "ser") == 0) {

    /* convert the serial strings to BIGNUM */
    BN_dec2bn(&startserialbn, startserstr);
    BN_dec2bn(&endserialbn, endserstr);

    /* get the certificates serial number and convert it to BIGNUM */
    if ((certserial = X509_get_serialNumber(cert)) == NULL)
       int_error("Error: Getting certificate serial number in ASN1 format.");
    if ((certserialbn = ASN1_INTEGER_to_BN(certserial, NULL)) == NULL)
       int_error("Error: converting certserial number from ASN1 to BIGNUM.");

    /* debugging output to see values of BIGNUM */
    //membio = BIO_new(BIO_s_mem());
    //BN_print(membio, endserialbn);
    //BIO_gets(membio, membio_buf, sizeof(membio_buf));
    //BIO_free(membio);
    //int_error(membio_buf);

    /* check if certserial >= startserial and <= endserial */
    if ( BN_cmp(startserialbn, certserialbn) <= 0 &&
         BN_cmp(endserialbn, certserialbn) >= 0 ) return 1;
  }

  return 0;
}
示例#23
0
文件: ocsp_lib.c 项目: 0culus/openssl
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, int *pssl)
	{
	char *p, *buf;

	char *host, *port;

	*phost = NULL;
	*pport = NULL;
	*ppath = NULL;

	/* dup the buffer since we are going to mess with it */
	buf = BUF_strdup(url);
	if (!buf) goto mem_err;

	/* Check for initial colon */
	p = strchr(buf, ':');

	if (!p) goto parse_err;

	*(p++) = '\0';

	if (!strcmp(buf, "http"))
		{
		*pssl = 0;
		port = "80";
		}
	else if (!strcmp(buf, "https"))
		{
		*pssl = 1;
		port = "443";
		}
	else
		goto parse_err;

	/* Check for double slash */
	if ((p[0] != '/') || (p[1] != '/'))
		goto parse_err;

	p += 2;

	host = p;

	/* Check for trailing part of path */

	p = strchr(p, '/');

	if (!p) 
		*ppath = BUF_strdup("/");
	else
		{
		*ppath = BUF_strdup(p);
		/* Set start of path to 0 so hostname is valid */
		*p = '\0';
		}

	if (!*ppath) goto mem_err;

	/* Look for optional ':' for port number */
	if ((p = strchr(host, ':')))
		{
		*p = 0;
		port = p + 1;
		}
	else
		{
		/* Not found: set default port */
		if (*pssl) port = "443";
		else port = "80";
		}

	*pport = BUF_strdup(port);
	if (!*pport) goto mem_err;

	*phost = BUF_strdup(host);

	if (!*phost) goto mem_err;

	OPENSSL_free(buf);

	return 1;

	mem_err:
	OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
	goto err;

	parse_err:
	OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);


	err:
	if (buf) OPENSSL_free(buf);
	if (*ppath) OPENSSL_free(*ppath);
	if (*pport) OPENSSL_free(*pport);
	if (*phost) OPENSSL_free(*phost);
	return 0;

	}
示例#24
0
文件: cms.c 项目: GH-JY/openssl
int cms_main(int argc, char **argv)
{
    ASN1_OBJECT *econtent_type = NULL;
    BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
    CMS_ContentInfo *cms = NULL, *rcms = NULL;
    CMS_ReceiptRequest *rr = NULL;
    ENGINE *e = NULL;
    EVP_PKEY *key = NULL;
    const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
    const EVP_MD *sign_md = NULL;
    STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
    char *CAfile = NULL, *CApath = NULL, *certsoutfile = NULL;
    int noCAfile = 0, noCApath = 0;
    char *infile = NULL, *outfile = NULL, *rctfile = NULL, *inrand = NULL;
    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile =
        NULL;
    char *to = NULL, *from = NULL, *subject = NULL, *prog;
    cms_key_param *key_first = NULL, *key_param = NULL;
    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched =
        0;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
    int need_rand = 0, operation = 0, ret = 1, rr_print = 0, rr_allorfirst =
        -1;
    int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
    size_t secret_keylen = 0, secret_keyidlen = 0;
    unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
    unsigned char *secret_key = NULL, *secret_keyid = NULL;
    long ltmp;
    OPTION_CHOICE o;

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, cms_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(cms_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENCRYPT:
            operation = SMIME_ENCRYPT;
            break;
        case OPT_DECRYPT:
            operation = SMIME_DECRYPT;
            break;
        case OPT_SIGN:
            operation = SMIME_SIGN;
            break;
        case OPT_SIGN_RECEIPT:
            operation = SMIME_SIGN_RECEIPT;
            break;
        case OPT_RESIGN:
            operation = SMIME_RESIGN;
            break;
        case OPT_VERIFY:
            operation = SMIME_VERIFY;
            break;
        case OPT_VERIFY_RETCODE:
            verify_retcode = 1;
            break;
        case OPT_VERIFY_RECEIPT:
            operation = SMIME_VERIFY_RECEIPT;
            rctfile = opt_arg();
            break;
        case OPT_CMSOUT:
            operation = SMIME_CMSOUT;
            break;
        case OPT_DATA_OUT:
            operation = SMIME_DATAOUT;
            break;
        case OPT_DATA_CREATE:
            operation = SMIME_DATA_CREATE;
            break;
        case OPT_DIGEST_VERIFY:
            operation = SMIME_DIGEST_VERIFY;
            break;
        case OPT_DIGEST_CREATE:
            operation = SMIME_DIGEST_CREATE;
            break;
        case OPT_COMPRESS:
            operation = SMIME_COMPRESS;
            break;
        case OPT_UNCOMPRESS:
            operation = SMIME_UNCOMPRESS;
            break;
        case OPT_ED_DECRYPT:
            operation = SMIME_ENCRYPTED_DECRYPT;
            break;
        case OPT_ED_ENCRYPT:
            operation = SMIME_ENCRYPTED_ENCRYPT;
            break;
        case OPT_DEBUG_DECRYPT:
            flags |= CMS_DEBUG_DECRYPT;
            break;
        case OPT_TEXT:
            flags |= CMS_TEXT;
            break;
        case OPT_ASCIICRLF:
            flags |= CMS_ASCIICRLF;
            break;
        case OPT_NOINTERN:
            flags |= CMS_NOINTERN;
            break;
        case OPT_NOVERIFY:
            flags |= CMS_NO_SIGNER_CERT_VERIFY;
            break;
        case OPT_NOCERTS:
            flags |= CMS_NOCERTS;
            break;
        case OPT_NOATTR:
            flags |= CMS_NOATTR;
            break;
        case OPT_NODETACH:
            flags &= ~CMS_DETACHED;
            break;
        case OPT_NOSMIMECAP:
            flags |= CMS_NOSMIMECAP;
            break;
        case OPT_BINARY:
            flags |= CMS_BINARY;
            break;
        case OPT_KEYID:
            flags |= CMS_USE_KEYID;
            break;
        case OPT_NOSIGS:
            flags |= CMS_NOSIGS;
            break;
        case OPT_NO_CONTENT_VERIFY:
            flags |= CMS_NO_CONTENT_VERIFY;
            break;
        case OPT_NO_ATTR_VERIFY:
            flags |= CMS_NO_ATTR_VERIFY;
            break;
        case OPT_INDEF:
            flags |= CMS_STREAM;
            break;
        case OPT_NOINDEF:
            flags &= ~CMS_STREAM;
            break;
        case OPT_NOOLDMIME:
            flags |= CMS_NOOLDMIMETYPE;
            break;
        case OPT_CRLFEOL:
            flags |= CMS_CRLFEOL;
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_RR_PRINT:
            rr_print = 1;
            break;
        case OPT_RR_ALL:
            rr_allorfirst = 0;
            break;
        case OPT_RR_FIRST:
            rr_allorfirst = 1;
            break;
        case OPT_RCTFORM:
            if (rctformat == FORMAT_SMIME)
                rcms = SMIME_read_CMS(rctin, NULL);
            else if (rctformat == FORMAT_PEM)
                rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
            else if (rctformat == FORMAT_ASN1)
                if (!opt_format(opt_arg(),
                                OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
                    goto opthelp;
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_CONTENT:
            contfile = opt_arg();
            break;
        case OPT_RR_FROM:
            if (rr_from == NULL
                && (rr_from = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(rr_from, opt_arg());
            break;
        case OPT_RR_TO:
            if (rr_to == NULL
                && (rr_to = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(rr_to, opt_arg());
            break;
        case OPT_PRINT:
            noout = print = 1;
            break;
        case OPT_SECRETKEY:
            secret_key = string_to_hex(opt_arg(), &ltmp);
            if (secret_key == NULL) {
                BIO_printf(bio_err, "Invalid key %s\n", opt_arg());
                goto end;
            }
            secret_keylen = (size_t)ltmp;
            break;
        case OPT_SECRETKEYID:
            secret_keyid = string_to_hex(opt_arg(), &ltmp);
            if (secret_keyid == NULL) {
                BIO_printf(bio_err, "Invalid id %s\n", opt_arg());
                goto opthelp;
            }
            secret_keyidlen = (size_t)ltmp;
            break;
        case OPT_PWRI_PASSWORD:
            pwri_pass = (unsigned char *)opt_arg();
            break;
        case OPT_ECONTENT_TYPE:
            econtent_type = OBJ_txt2obj(opt_arg(), 0);
            if (econtent_type == NULL) {
                BIO_printf(bio_err, "Invalid OID %s\n", opt_arg());
                goto opthelp;
            }
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_TO:
            to = opt_arg();
            break;
        case OPT_FROM:
            from = opt_arg();
            break;
        case OPT_SUBJECT:
            subject = opt_arg();
            break;
        case OPT_CERTSOUT:
            certsoutfile = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &sign_md))
                goto end;
            break;
        case OPT_SIGNER:
            /* If previous -signer argument add signer to list */
            if (signerfile) {
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (keyfile == NULL)
                    keyfile = signerfile;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = opt_arg();
            break;
        case OPT_INKEY:
            /* If previous -inkey arument add signer to list */
            if (keyfile) {
                if (signerfile == NULL) {
                    BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    goto end;
                }
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
                goto opthelp;
            break;
        case OPT_RECIP:
            if (operation == SMIME_ENCRYPT) {
                if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
                    goto end;
                cert = load_cert(opt_arg(), FORMAT_PEM, NULL, e,
                                 "recipient certificate file");
                if (cert == NULL)
                    goto end;
                sk_X509_push(encerts, cert);
                cert = NULL;
            } else
                recipfile = opt_arg();
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &cipher))
                goto end;
            break;
        case OPT_KEYOPT:
            keyidx = -1;
            if (operation == SMIME_ENCRYPT) {
                if (encerts)
                    keyidx += sk_X509_num(encerts);
            } else {
                if (keyfile || signerfile)
                    keyidx++;
                if (skkeys)
                    keyidx += sk_OPENSSL_STRING_num(skkeys);
            }
            if (keyidx < 0) {
                BIO_printf(bio_err, "No key specified\n");
                goto opthelp;
            }
            if (key_param == NULL || key_param->idx != keyidx) {
                cms_key_param *nparam;
                nparam = app_malloc(sizeof(*nparam), "key param buffer");
                nparam->idx = keyidx;
                if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                nparam->next = NULL;
                if (key_first == NULL)
                    key_first = nparam;
                else
                    key_param->next = nparam;
                key_param = nparam;
            }
            sk_OPENSSL_STRING_push(key_param->param, opt_arg());
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_3DES_WRAP:
# ifndef OPENSSL_NO_DES
            wrap_cipher = EVP_des_ede3_wrap();
# endif
            break;
# ifndef OPENSSL_NO_AES
        case OPT_AES128_WRAP:
            wrap_cipher = EVP_aes_128_wrap();
            break;
        case OPT_AES192_WRAP:
            wrap_cipher = EVP_aes_192_wrap();
            break;
        case OPT_AES256_WRAP:
            wrap_cipher = EVP_aes_256_wrap();
            break;
# else
        case OPT_AES128_WRAP:
        case OPT_AES192_WRAP:
        case OPT_AES256_WRAP:
            break;
# endif
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (((rr_allorfirst != -1) || rr_from) && !rr_to) {
        BIO_puts(bio_err, "No Signed Receipts Recipients\n");
        goto opthelp;
    }

    if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) {
        BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
        goto opthelp;
    }
    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto opthelp;
    }

    if (operation & SMIME_SIGNERS) {
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto opthelp;
        }
        /* Check to see if any final signer needs to be appended */
        if (signerfile) {
            if (!sksigners
                && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            goto opthelp;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    }

    else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile && !secret_key && !pwri_pass) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            goto opthelp;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (*argv == NULL && !secret_key && !pwri_pass && !encerts) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            goto opthelp;
        }
        need_rand = 1;
    } else if (!operation)
        goto opthelp;

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~CMS_DETACHED;

    if (!(operation & SMIME_OP)) {
        if (flags & CMS_BINARY)
            outformat = FORMAT_BINARY;
    }

    if (!(operation & SMIME_IP)) {
        if (flags & CMS_BINARY)
            informat = FORMAT_BINARY;
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
# ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
# else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
# endif
        }

        if (secret_key && !secret_keyid) {
            BIO_printf(bio_err, "No secret key id\n");
            goto end;
        }

        if (*argv && !encerts)
            if ((encerts = sk_X509_new_null()) == NULL)
                goto end;
        while (*argv) {
            if ((cert = load_cert(*argv, FORMAT_PEM, NULL, e,
                                  "recipient certificate file")) == NULL)
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            argv++;
        }
    }

    if (certfile) {
        if ((other = load_certs(certfile, FORMAT_PEM, NULL, e,
                                "certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if ((recip = load_cert(recipfile, FORMAT_PEM, NULL, e,
                               "recipient certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_SIGN_RECEIPT) {
        if ((signer = load_cert(signerfile, FORMAT_PEM, NULL, e,
                                "receipt signer certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
        if (!key)
            goto end;
    }

    in = bio_open_default(infile, 'r', informat);
    if (in == NULL)
        goto end;

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            cms = SMIME_read_CMS(in, &indata);
        else if (informat == FORMAT_PEM)
            cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            cms = d2i_CMS_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for CMS file\n");
            goto end;
        }

        if (!cms) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
        if (certsoutfile) {
            STACK_OF(X509) *allcerts;
            allcerts = CMS_get1_certs(cms);
            if (!save_certs(certsoutfile, allcerts)) {
                BIO_printf(bio_err,
                           "Error writing certs to %s\n", certsoutfile);
                ret = 5;
                goto end;
            }
            sk_X509_pop_free(allcerts, X509_free);
        }
    }

    if (rctfile) {
        char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
        if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
            BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
            goto end;
        }

        if (rctformat == FORMAT_SMIME)
            rcms = SMIME_read_CMS(rctin, NULL);
        else if (rctformat == FORMAT_PEM)
            rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
        else if (rctformat == FORMAT_ASN1)
            rcms = d2i_CMS_bio(rctin, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for receipt\n");
            goto end;
        }

        if (!rcms) {
            BIO_printf(bio_err, "Error reading receipt\n");
            goto end;
        }
    }

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        X509_STORE_set_verify_cb(store, cms_cb);
        if (vpmtouched)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_DATA_CREATE) {
        cms = CMS_data_create(in, flags);
    } else if (operation == SMIME_DIGEST_CREATE) {
        cms = CMS_digest_create(in, sign_md, flags);
    } else if (operation == SMIME_COMPRESS) {
        cms = CMS_compress(in, -1, flags);
    } else if (operation == SMIME_ENCRYPT) {
        int i;
        flags |= CMS_PARTIAL;
        cms = CMS_encrypt(NULL, in, cipher, flags);
        if (!cms)
            goto end;
        for (i = 0; i < sk_X509_num(encerts); i++) {
            CMS_RecipientInfo *ri;
            cms_key_param *kparam;
            int tflags = flags;
            X509 *x = sk_X509_value(encerts, i);
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            ri = CMS_add1_recipient_cert(cms, x, tflags);
            if (!ri)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
                && wrap_cipher) {
                EVP_CIPHER_CTX *wctx;
                wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
                EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
            }
        }

        if (secret_key) {
            if (!CMS_add0_recipient_key(cms, NID_undef,
                                        secret_key, secret_keylen,
                                        secret_keyid, secret_keyidlen,
                                        NULL, NULL, NULL))
                goto end;
            /* NULL these because call absorbs them */
            secret_key = NULL;
            secret_keyid = NULL;
        }
        if (pwri_pass) {
            pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass);
            if (!pwri_tmp)
                goto end;
            if (!CMS_add0_recipient_password(cms,
                                             -1, NID_undef, NID_undef,
                                             pwri_tmp, -1, NULL))
                goto end;
            pwri_tmp = NULL;
        }
        if (!(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
        cms = CMS_EncryptedData_encrypt(in, cipher,
                                        secret_key, secret_keylen, flags);

    } else if (operation == SMIME_SIGN_RECEIPT) {
        CMS_ContentInfo *srcms = NULL;
        STACK_OF(CMS_SignerInfo) *sis;
        CMS_SignerInfo *si;
        sis = CMS_get0_SignerInfos(cms);
        if (!sis)
            goto end;
        si = sk_CMS_SignerInfo_value(sis, 0);
        srcms = CMS_sign_receipt(si, signer, key, other, flags);
        if (!srcms)
            goto end;
        CMS_ContentInfo_free(cms);
        cms = srcms;
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {

            if (flags & CMS_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= CMS_STREAM;
            }
            flags |= CMS_PARTIAL;
            cms = CMS_sign(NULL, NULL, other, in, flags);
            if (!cms)
                goto end;
            if (econtent_type)
                CMS_set1_eContentType(cms, econtent_type);

            if (rr_to) {
                rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
                if (!rr) {
                    BIO_puts(bio_err,
                             "Signed Receipt Request Creation Error\n");
                    goto end;
                }
            }
        } else
            flags |= CMS_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            CMS_SignerInfo *si;
            cms_key_param *kparam;
            int tflags = flags;
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);

            signer = load_cert(signerfile, FORMAT_PEM, NULL,
                               e, "signer certificate");
            if (!signer)
                goto end;
            key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
            if (!key)
                goto end;
            for (kparam = key_first; kparam; kparam = kparam->next) {
                if (kparam->idx == i) {
                    tflags |= CMS_KEY_PARAM;
                    break;
                }
            }
            si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
            if (!si)
                goto end;
            if (kparam) {
                EVP_PKEY_CTX *pctx;
                pctx = CMS_SignerInfo_get0_pkey_ctx(si);
                if (!cms_set_pkey_param(pctx, kparam->param))
                    goto end;
            }
            if (rr && !CMS_add1_ReceiptRequest(si, rr))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
            if (!CMS_final(cms, in, NULL, flags))
                goto end;
        }
    }

    if (!cms) {
        BIO_printf(bio_err, "Error creating CMS structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (flags & CMS_DEBUG_DECRYPT)
            CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);

        if (secret_key) {
            if (!CMS_decrypt_set1_key(cms,
                                      secret_key, secret_keylen,
                                      secret_keyid, secret_keyidlen)) {
                BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
                goto end;
            }
        }

        if (key) {
            if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
                BIO_puts(bio_err, "Error decrypting CMS using private key\n");
                goto end;
            }
        }

        if (pwri_pass) {
            if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
                BIO_puts(bio_err, "Error decrypting CMS using password\n");
                goto end;
            }
        }

        if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
            BIO_printf(bio_err, "Error decrypting CMS structure\n");
            goto end;
        }
    } else if (operation == SMIME_DATAOUT) {
        if (!CMS_data(cms, out, flags))
            goto end;
    } else if (operation == SMIME_UNCOMPRESS) {
        if (!CMS_uncompress(cms, indata, out, flags))
            goto end;
    } else if (operation == SMIME_DIGEST_VERIFY) {
        if (CMS_digest_verify(cms, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else if (operation == SMIME_ENCRYPTED_DECRYPT) {
        if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
                                       indata, out, flags))
            goto end;
    } else if (operation == SMIME_VERIFY) {
        if (CMS_verify(cms, other, store, indata, out, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            if (verify_retcode)
                ret = verify_err + 32;
            goto end;
        }
        if (signerfile) {
            STACK_OF(X509) *signers;
            signers = CMS_get0_signers(cms);
            if (!save_certs(signerfile, signers)) {
                BIO_printf(bio_err,
                           "Error writing signers to %s\n", signerfile);
                ret = 5;
                goto end;
            }
            sk_X509_free(signers);
        }
        if (rr_print)
            receipt_request_print(cms);

    } else if (operation == SMIME_VERIFY_RECEIPT) {
        if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
    } else {
        if (noout) {
            if (print)
                CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
        } else if (outformat == FORMAT_SMIME) {
            if (to)
                BIO_printf(out, "To: %s\n", to);
            if (from)
                BIO_printf(out, "From: %s\n", from);
            if (subject)
                BIO_printf(out, "Subject: %s\n", subject);
            if (operation == SMIME_RESIGN)
                ret = SMIME_write_CMS(out, cms, indata, flags);
            else
                ret = SMIME_write_CMS(out, cms, in, flags);
        } else if (outformat == FORMAT_PEM)
            ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
        else if (outformat == FORMAT_ASN1)
            ret = i2d_CMS_bio_stream(out, cms, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for CMS file\n");
            goto end;
        }
        if (ret <= 0) {
            ret = 6;
            goto end;
        }
    }
    ret = 0;
 end:
    if (ret)
        ERR_print_errors(bio_err);
    if (need_rand)
        app_RAND_write_file(NULL);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    X509_VERIFY_PARAM_free(vpm);
    sk_OPENSSL_STRING_free(sksigners);
    sk_OPENSSL_STRING_free(skkeys);
    OPENSSL_free(secret_key);
    OPENSSL_free(secret_keyid);
    OPENSSL_free(pwri_tmp);
    ASN1_OBJECT_free(econtent_type);
    CMS_ReceiptRequest_free(rr);
    sk_OPENSSL_STRING_free(rr_to);
    sk_OPENSSL_STRING_free(rr_from);
    for (key_param = key_first; key_param;) {
        cms_key_param *tparam;
        sk_OPENSSL_STRING_free(key_param->param);
        tparam = key_param->next;
        OPENSSL_free(key_param);
        key_param = tparam;
    }
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    CMS_ContentInfo_free(cms);
    CMS_ContentInfo_free(rcms);
    BIO_free(rctin);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    OPENSSL_free(passin);
    return (ret);
}
示例#25
0
static long set_CCA4758_LIB_NAME(const char *name)
	{
	free_CCA4758_LIB_NAME();
	return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
示例#26
0
SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
  SSL_SESSION *new_session = ssl_session_new(session->x509_method);
  if (new_session == NULL) {
    goto err;
  }

  new_session->is_server = session->is_server;
  new_session->ssl_version = session->ssl_version;
  new_session->sid_ctx_length = session->sid_ctx_length;
  OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);

  /* Copy the key material. */
  new_session->master_key_length = session->master_key_length;
  OPENSSL_memcpy(new_session->master_key, session->master_key,
         session->master_key_length);
  new_session->cipher = session->cipher;

  /* Copy authentication state. */
  if (session->psk_identity != NULL) {
    new_session->psk_identity = BUF_strdup(session->psk_identity);
    if (new_session->psk_identity == NULL) {
      goto err;
    }
  }
  if (session->certs != NULL) {
    new_session->certs = sk_CRYPTO_BUFFER_new_null();
    if (new_session->certs == NULL) {
      goto err;
    }
    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
      CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
      if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
        goto err;
      }
      CRYPTO_BUFFER_up_ref(buffer);
    }
  }

  if (!session->x509_method->session_dup(new_session, session)) {
    goto err;
  }

  new_session->verify_result = session->verify_result;

  new_session->ocsp_response_length = session->ocsp_response_length;
  if (session->ocsp_response != NULL) {
    new_session->ocsp_response = BUF_memdup(session->ocsp_response,
                                            session->ocsp_response_length);
    if (new_session->ocsp_response == NULL) {
      goto err;
    }
  }

  new_session->tlsext_signed_cert_timestamp_list_length =
      session->tlsext_signed_cert_timestamp_list_length;
  if (session->tlsext_signed_cert_timestamp_list != NULL) {
    new_session->tlsext_signed_cert_timestamp_list =
        BUF_memdup(session->tlsext_signed_cert_timestamp_list,
                   session->tlsext_signed_cert_timestamp_list_length);
    if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
      goto err;
    }
  }

  OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
                 SHA256_DIGEST_LENGTH);
  new_session->peer_sha256_valid = session->peer_sha256_valid;

  if (session->tlsext_hostname != NULL) {
    new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
    if (new_session->tlsext_hostname == NULL) {
      goto err;
    }
  }

  new_session->peer_signature_algorithm = session->peer_signature_algorithm;

  new_session->timeout = session->timeout;
  new_session->auth_timeout = session->auth_timeout;
  new_session->time = session->time;

  /* Copy non-authentication connection properties. */
  if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
    new_session->session_id_length = session->session_id_length;
    OPENSSL_memcpy(new_session->session_id, session->session_id,
                   session->session_id_length);

    new_session->group_id = session->group_id;

    OPENSSL_memcpy(new_session->original_handshake_hash,
                   session->original_handshake_hash,
                   session->original_handshake_hash_len);
    new_session->original_handshake_hash_len =
        session->original_handshake_hash_len;
    new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
    new_session->ticket_age_add = session->ticket_age_add;
    new_session->ticket_max_early_data = session->ticket_max_early_data;
    new_session->extended_master_secret = session->extended_master_secret;

    if (session->early_alpn != NULL) {
      new_session->early_alpn =
          BUF_memdup(session->early_alpn, session->early_alpn_len);
      if (new_session->early_alpn == NULL) {
        goto err;
      }
    }
    new_session->early_alpn_len = session->early_alpn_len;
  }

  /* Copy the ticket. */
  if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
    if (session->tlsext_tick != NULL) {
      new_session->tlsext_tick =
          BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
      if (new_session->tlsext_tick == NULL) {
        goto err;
      }
    }
    new_session->tlsext_ticklen = session->tlsext_ticklen;
  }

  /* The new_session does not get a copy of the ex_data. */

  new_session->not_resumable = 1;
  return new_session;

err:
  SSL_SESSION_free(new_session);
  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  return 0;
}
示例#27
0
static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
	{
	int ret = 1;
	CAPI_CTX *ctx;
	BIO *out;
	if (capi_idx == -1)
		{
		CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
		return 0;
		}
	ctx = ENGINE_get_ex_data(e, capi_idx);
	out = BIO_new_fp(stdout, BIO_NOCLOSE);
	switch (cmd)
		{
		case CAPI_CMD_LIST_CSPS:
		ret = capi_list_providers(ctx, out);
		break;

		case CAPI_CMD_LIST_CERTS:
		ret = capi_list_certs(ctx, out, NULL);
		break;

		case CAPI_CMD_LOOKUP_CERT:
		ret = capi_list_certs(ctx, out, p);
		break;

		case CAPI_CMD_LIST_CONTAINERS:
		ret = capi_list_containers(ctx, out);
		break;

		case CAPI_CMD_STORE_NAME:
		if (ctx->storename)
			OPENSSL_free(ctx->storename);
		ctx->storename = BUF_strdup(p);
		CAPI_trace(ctx, "Setting store name to %s\n", p);
		break;

		case CAPI_CMD_STORE_FLAGS:
		if (i & 1)
			{
			ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
			ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
			}
		else
			{
			ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
			ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
			}
		CAPI_trace(ctx, "Setting flags to %d\n", i);
		break;

		case CAPI_CMD_DEBUG_LEVEL:
		ctx->debug_level = (int)i;
		CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
		break;

		case CAPI_CMD_DEBUG_FILE:
		ctx->debug_file = BUF_strdup(p);
		CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
		break;

		case CAPI_CMD_KEYTYPE:
		ctx->keytype = i;
		CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
		break;

		case CAPI_CMD_SET_CSP_IDX:
		ret = capi_ctx_set_provname_idx(ctx, i);
		break;

		case CAPI_CMD_LIST_OPTIONS:
		ctx->dump_flags = i;
		break;

		case CAPI_CMD_LOOKUP_METHOD:
		if (i < 1 || i > 3)
			{
			CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
			return 0;
			}
		ctx->lookup_method = i;
		break;

		case CAPI_CMD_SET_CSP_NAME:
		ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
		break;

		case CAPI_CMD_SET_CSP_TYPE:
		ctx->csptype = i;
		break;

		default:
		CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
		ret = 0;
	}

	BIO_free(out);
	return ret;

	}
示例#28
0
int main(int argc, char *argv[])
	{
	ENGINE *block[512];
	char buf[256];
	const char *id, *name;
	ENGINE *ptr;
	int loop;
	int to_return = 1;
	ENGINE *new_h1 = NULL;
	ENGINE *new_h2 = NULL;
	ENGINE *new_h3 = NULL;
	ENGINE *new_h4 = NULL;

	/* enable memory leak checking unless explicitly disabled */
	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
		{
		CRYPTO_malloc_debug_init();
		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
		}
	else
		{
		/* OPENSSL_DEBUG_MEMORY=off */
		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
		}
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
	ERR_load_crypto_strings();

	memset(block, 0, 512 * sizeof(ENGINE *));
	if(((new_h1 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h1, "test_id0") ||
			!ENGINE_set_name(new_h1, "First test item") ||
			((new_h2 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h2, "test_id1") ||
			!ENGINE_set_name(new_h2, "Second test item") ||
			((new_h3 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h3, "test_id2") ||
			!ENGINE_set_name(new_h3, "Third test item") ||
			((new_h4 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h4, "test_id3") ||
			!ENGINE_set_name(new_h4, "Fourth test item"))
		{
		printf("Couldn't set up test ENGINE structures\n");
		goto end;
		}
	printf("\nenginetest beginning\n\n");
	display_engine_list();
	if(!ENGINE_add(new_h1))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	ptr = ENGINE_get_first();
	if(!ENGINE_remove(ptr))
		{
		printf("Remove failed!\n");
		goto end;
		}
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h2))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_add(new_h4))
		{
		printf("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(ENGINE_add(new_h3))
		{
		printf("Add *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Add that should fail did.\n");
	ERR_clear_error();
	if(ENGINE_remove(new_h2))
		{
		printf("Remove *should* have failed but didn't!\n");
		goto end;
		}
	else
		printf("Remove that should fail did.\n");
	ERR_clear_error();
	if(!ENGINE_remove(new_h3))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h4))
		{
		printf("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	/* Depending on whether there's any hardware support compiled
	 * in, this remove may be destined to fail. */
	ptr = ENGINE_get_first();
	if(ptr)
		if(!ENGINE_remove(ptr))
			printf("Remove failed!i - probably no hardware "
				"support present.\n");
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1))
		{
		printf("Couldn't add and remove to an empty list!\n");
		goto end;
		}
	else
		printf("Successfully added and removed to an empty list!\n");
	printf("About to beef up the engine-type list\n");
	for(loop = 0; loop < 512; loop++)
		{
		sprintf(buf, "id%i", loop);
		id = BUF_strdup(buf);
		sprintf(buf, "Fake engine type %i", loop);
		name = BUF_strdup(buf);
		if(((block[loop] = ENGINE_new()) == NULL) ||
				!ENGINE_set_id(block[loop], id) ||
				!ENGINE_set_name(block[loop], name))
			{
			printf("Couldn't create block of ENGINE structures.\n"
				"I'll probably also core-dump now, damn.\n");
			goto end;
			}
		}
	for(loop = 0; loop < 512; loop++)
		{
		if(!ENGINE_add(block[loop]))
			{
			printf("\nAdding stopped at %i, (%s,%s)\n",
				loop, ENGINE_get_id(block[loop]),
				ENGINE_get_name(block[loop]));
			goto cleanup_loop;
			}
		else
			printf("."); fflush(stdout);
		}
cleanup_loop:
	printf("\nAbout to empty the engine-type list\n");
	while((ptr = ENGINE_get_first()) != NULL)
		{
		if(!ENGINE_remove(ptr))
			{
			printf("\nRemove failed!\n");
			goto end;
			}
		ENGINE_free(ptr);
		printf("."); fflush(stdout);
		}
	for(loop = 0; loop < 512; loop++)
		{
		OPENSSL_free((void *)ENGINE_get_id(block[loop]));
		OPENSSL_free((void *)ENGINE_get_name(block[loop]));
		}
	printf("\nTests completed happily\n");
	to_return = 0;
end:
	if(to_return)
		ERR_print_errors_fp(stderr);
	if(new_h1) ENGINE_free(new_h1);
	if(new_h2) ENGINE_free(new_h2);
	if(new_h3) ENGINE_free(new_h3);
	if(new_h4) ENGINE_free(new_h4);
	for(loop = 0; loop < 512; loop++)
		if(block[loop])
			ENGINE_free(block[loop]);
	ENGINE_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_thread_state(NULL);
	CRYPTO_mem_leaks_fp(stderr);
	return to_return;
	}
示例#29
0
static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
	{
	BIO *dbio;
	int *ip;
	long ret=1;
	BIO_ACCEPT *data;
	char **pp;

	data=(BIO_ACCEPT *)b->ptr;

	switch (cmd)
		{
	case BIO_CTRL_RESET:
		ret=0;
		data->state=ACPT_S_BEFORE;
		acpt_close_socket(b);
		b->flags=0;
		break;
	case BIO_C_DO_STATE_MACHINE:
		/* use this one to start the connection */
		ret=(long)acpt_state(b,data);
		break;
	case BIO_C_SET_ACCEPT:
		if (ptr != NULL)
			{
			if (num == 0)
				{
				b->init=1;
				if (data->param_addr != NULL)
					OPENSSL_free(data->param_addr);
				data->param_addr=BUF_strdup(ptr);
				}
			else if (num == 1)
				{
				data->accept_nbio=(ptr != NULL);
				}
			else if (num == 2)
				{
				if (data->bio_chain != NULL)
					BIO_free(data->bio_chain);
				data->bio_chain=(BIO *)ptr;
				}
			}
		break;
	case BIO_C_SET_NBIO:
		data->nbio=(int)num;
		break;
	case BIO_C_SET_FD:
		b->init=1;
		b->num= *((int *)ptr);
		data->accept_sock=b->num;
		data->state=ACPT_S_GET_ACCEPT_SOCKET;
		b->shutdown=(int)num;
		b->init=1;
		break;
	case BIO_C_GET_FD:
		if (b->init)
			{
			ip=(int *)ptr;
			if (ip != NULL)
				*ip=data->accept_sock;
			ret=data->accept_sock;
			}
		else
			ret= -1;
		break;
	case BIO_C_GET_ACCEPT:
		if (b->init)
			{
			if (ptr != NULL)
				{
				pp=(char **)ptr;
				*pp=data->param_addr;
				}
			else
				ret= -1;
			}
		else
			ret= -1;
		break;
	case BIO_CTRL_GET_CLOSE:
		ret=b->shutdown;
		break;
	case BIO_CTRL_SET_CLOSE:
		b->shutdown=(int)num;
		break;
	case BIO_CTRL_PENDING:
	case BIO_CTRL_WPENDING:
		ret=0;
		break;
	case BIO_CTRL_FLUSH:
		break;
	case BIO_C_SET_BIND_MODE:
		data->bind_mode=(int)num;
		break;
	case BIO_C_GET_BIND_MODE:
		ret=(long)data->bind_mode;
		break;
	case BIO_CTRL_DUP:
		dbio=(BIO *)ptr;
/*		if (data->param_port) EAY EAY
			BIO_set_port(dbio,data->param_port);
		if (data->param_hostname)
			BIO_set_hostname(dbio,data->param_hostname);
		BIO_set_nbio(dbio,data->nbio); */
		break;

	default:
		ret=0;
		break;
		}
	return(ret);
	}
示例#30
0
文件: srp.c 项目: Chatlanen/openssl
int srp_main(int argc, char **argv)
{
    CA_DB *db = NULL;
    DB_ATTR db_attr;
    CONF *conf = NULL;
    int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose =
        0, i, doupdatedb = 0;
    int mode = OPT_ERR;
    char *user = NULL, *passinarg = NULL, *passoutarg = NULL;
    char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;
    char *randfile = NULL, *tofree = NULL, *section = NULL;
    char **gNrow = NULL, *configfile = NULL, *dbfile = NULL, **pp, *prog;
    long errorline = -1;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, srp_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(srp_options);
            ret = 0;
            goto end;
        case OPT_VERBOSE:
            verbose++;
            break;
        case OPT_CONFIG:
            configfile = opt_arg();
            break;
        case OPT_NAME:
            section = opt_arg();
            break;
        case OPT_SRPVFILE:
            dbfile = opt_arg();
            break;
        case OPT_ADD:
        case OPT_DELETE:
        case OPT_MODIFY:
        case OPT_LIST:
            if (mode != OPT_ERR) {
                BIO_printf(bio_err,
                           "%s: Only one of -add/delete-modify/-list\n",
                           prog);
                goto opthelp;
            }
            mode = o;
            break;
        case OPT_GN:
            gN = opt_arg();
            break;
        case OPT_USERINFO:
            userinfo = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_PASSOUT:
            passoutarg = opt_arg();
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (dbfile && configfile) {
        BIO_printf(bio_err,
                   "-dbfile and -configfile cannot be specified together.\n");
        goto end;
    }
    if (mode == OPT_ERR) {
        BIO_printf(bio_err,
                   "Exactly one of the options -add, -delete, -modify -list must be specified.\n");
        goto opthelp;
    }
    if ((mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD)
        && argc < 1) {
        BIO_printf(bio_err,
                   "Need at least one user for options -add, -delete, -modify. \n");
        goto opthelp;
    }
    if ((passin || passout) && argc != 1) {
        BIO_printf(bio_err,
                   "-passin, -passout arguments only valid with one user.\n");
        goto opthelp;
    }

    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
        BIO_printf(bio_err, "Error getting passwords\n");
        goto end;
    }

    if (!dbfile) {

        /*****************************************************************/
        tofree = NULL;
        if (configfile == NULL)
            configfile = getenv("OPENSSL_CONF");
        if (configfile == NULL)
            configfile = getenv("SSLEAY_CONF");
        if (configfile == NULL) {
            const char *s = X509_get_default_cert_area();
            size_t len = strlen(s) + 1 + sizeof(CONFIG_FILE);

            tofree = app_malloc(len, "config filename space");
# ifdef OPENSSL_SYS_VMS
            strcpy(tofree, s);
# else
            BUF_strlcpy(tofree, s, len);
            BUF_strlcat(tofree, "/", len);
# endif
            BUF_strlcat(tofree, CONFIG_FILE, len);
            configfile = tofree;
        }

        if (verbose)
            BIO_printf(bio_err, "Using configuration from %s\n", configfile);
        conf = NCONF_new(NULL);
        if (NCONF_load(conf, configfile, &errorline) <= 0) {
            if (errorline <= 0)
                BIO_printf(bio_err, "error loading the config file '%s'\n",
                           configfile);
            else
                BIO_printf(bio_err, "error on line %ld of config file '%s'\n",
                           errorline, configfile);
            goto end;
        }
        OPENSSL_free(tofree);
        tofree = NULL;

        /* Lets get the config section we are using */
        if (section == NULL) {
            if (verbose)
                BIO_printf(bio_err,
                           "trying to read " ENV_DEFAULT_SRP
                           " in \" BASE_SECTION \"\n");

            section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_SRP);
            if (section == NULL) {
                lookup_fail(BASE_SECTION, ENV_DEFAULT_SRP);
                goto end;
            }
        }

        if (randfile == NULL && conf)
            randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");

        if (verbose)
            BIO_printf(bio_err,
                       "trying to read " ENV_DATABASE " in section \"%s\"\n",
                       section);

        if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
            lookup_fail(section, ENV_DATABASE);
            goto end;
        }

    }
    if (randfile == NULL)
        ERR_clear_error();
    else
        app_RAND_load_file(randfile, 0);

    if (verbose)
        BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
                   dbfile);

    db = load_index(dbfile, &db_attr);
    if (db == NULL)
        goto end;

    /* Lets check some fields */
    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);

        if (pp[DB_srptype][0] == DB_SRP_INDEX) {
            maxgN = i;
            if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0)
                gNindex = i;

            print_index(db, i, verbose > 1);
        }
    }

    if (verbose)
        BIO_printf(bio_err, "Database initialised\n");

    if (gNindex >= 0) {
        gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
        print_entry(db, gNindex, verbose > 1, "Default g and N");
    } else if (maxgN > 0 && !SRP_get_default_gN(gN)) {
        BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
        goto end;
    } else {
        if (verbose)
            BIO_printf(bio_err, "Database has no g N information.\n");
        gNrow = NULL;
    }

    if (verbose > 1)
        BIO_printf(bio_err, "Starting user processing\n");

    if (argc > 0)
        user = *(argv++);

    while (mode == OPT_LIST || user) {
        int userindex = -1;
        if (user)
            if (verbose > 1)
                BIO_printf(bio_err, "Processing user \"%s\"\n", user);
        if ((userindex = get_index(db, user, 'U')) >= 0) {
            print_user(db, userindex, (verbose > 0)
                       || mode == OPT_LIST);
        }

        if (mode == OPT_LIST) {
            if (user == NULL) {
                BIO_printf(bio_err, "List all users\n");

                for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
                    print_user(db, i, 1);
                }
            } else if (userindex < 0) {
                BIO_printf(bio_err,
                           "user \"%s\" does not exist, ignored. t\n", user);
                errors++;
            }
        } else if (mode == OPT_ADD) {
            if (userindex >= 0) {
                /* reactivation of a new user */
                char **row =
                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);
                BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
                row[DB_srptype][0] = 'V';

                doupdatedb = 1;
            } else {
                char *row[DB_NUMBER];
                char *gNid;
                row[DB_srpverifier] = NULL;
                row[DB_srpsalt] = NULL;
                row[DB_srpinfo] = NULL;
                if (!
                    (gNid =
                     srp_create_user(user, &(row[DB_srpverifier]),
                                     &(row[DB_srpsalt]),
                                     gNrow ? gNrow[DB_srpsalt] : gN,
                                     gNrow ? gNrow[DB_srpverifier] : NULL,
                                     passout, verbose))) {
                    BIO_printf(bio_err,
                               "Cannot create srp verifier for user \"%s\", operation abandoned .\n",
                               user);
                    errors++;
                    goto end;
                }
                row[DB_srpid] = BUF_strdup(user);
                row[DB_srptype] = BUF_strdup("v");
                row[DB_srpgN] = BUF_strdup(gNid);

                if ((row[DB_srpid] == NULL)
                    || (row[DB_srpgN] == NULL)
                    || (row[DB_srptype] == NULL)
                    || (row[DB_srpverifier] == NULL)
                    || (row[DB_srpsalt] == NULL)
                    || (userinfo
                        && ((row[DB_srpinfo] = BUF_strdup(userinfo)) == NULL))
                    || !update_index(db, row)) {
                    OPENSSL_free(row[DB_srpid]);
                    OPENSSL_free(row[DB_srpgN]);
                    OPENSSL_free(row[DB_srpinfo]);
                    OPENSSL_free(row[DB_srptype]);
                    OPENSSL_free(row[DB_srpverifier]);
                    OPENSSL_free(row[DB_srpsalt]);
                    goto end;
                }
                doupdatedb = 1;
            }
        } else if (mode == OPT_MODIFY) {
            if (userindex < 0) {
                BIO_printf(bio_err,
                           "user \"%s\" does not exist, operation ignored.\n",
                           user);
                errors++;
            } else {

                char **row =
                    sk_OPENSSL_PSTRING_value(db->db->data, userindex);
                char type = row[DB_srptype][0];
                if (type == 'v') {
                    BIO_printf(bio_err,
                               "user \"%s\" already updated, operation ignored.\n",
                               user);
                    errors++;
                } else {
                    char *gNid;

                    if (row[DB_srptype][0] == 'V') {
                        int user_gN;
                        char **irow = NULL;
                        if (verbose)
                            BIO_printf(bio_err,
                                       "Verifying password for user \"%s\"\n",
                                       user);
                        if ((user_gN =
                             get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
                            irow =
                                sk_OPENSSL_PSTRING_value(db->db->data,
                                                         userindex);

                        if (!srp_verify_user
                            (user, row[DB_srpverifier], row[DB_srpsalt],
                             irow ? irow[DB_srpsalt] : row[DB_srpgN],
                             irow ? irow[DB_srpverifier] : NULL, passin,
                             verbose)) {
                            BIO_printf(bio_err,
                                       "Invalid password for user \"%s\", operation abandoned.\n",
                                       user);
                            errors++;
                            goto end;
                        }
                    }
                    if (verbose)
                        BIO_printf(bio_err, "Password for user \"%s\" ok.\n",
                                   user);

                    if (!
                        (gNid =
                         srp_create_user(user, &(row[DB_srpverifier]),
                                         &(row[DB_srpsalt]),
                                         gNrow ? gNrow[DB_srpsalt] : NULL,
                                         gNrow ? gNrow[DB_srpverifier] : NULL,
                                         passout, verbose))) {
                        BIO_printf(bio_err,
                                   "Cannot create srp verifier for user \"%s\", operation abandoned.\n",
                                   user);
                        errors++;
                        goto end;
                    }

                    row[DB_srptype][0] = 'v';
                    row[DB_srpgN] = BUF_strdup(gNid);

                    if (row[DB_srpid] == NULL
                        || row[DB_srpgN] == NULL
                        || row[DB_srptype] == NULL
                        || row[DB_srpverifier] == NULL
                        || row[DB_srpsalt] == NULL
                        || (userinfo
                            && ((row[DB_srpinfo] = BUF_strdup(userinfo))
                                == NULL)))
                        goto end;

                    doupdatedb = 1;
                }
            }
        } else if (mode == OPT_DELETE) {
            if (userindex < 0) {
                BIO_printf(bio_err,
                           "user \"%s\" does not exist, operation ignored. t\n",
                           user);
                errors++;
            } else {
                char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex);

                BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
                xpp[DB_srptype][0] = 'R';
                doupdatedb = 1;
            }
        }
        if (--argc > 0)
            user = *(argv++);
        else {
            user = NULL;
        }
    }

    if (verbose)
        BIO_printf(bio_err, "User procession done.\n");

    if (doupdatedb) {
        /* Lets check some fields */
        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);

            if (pp[DB_srptype][0] == 'v') {
                pp[DB_srptype][0] = 'V';
                print_user(db, i, verbose);
            }
        }

        if (verbose)
            BIO_printf(bio_err, "Trying to update srpvfile.\n");
        if (!save_index(dbfile, "new", db))
            goto end;

        if (verbose)
            BIO_printf(bio_err, "Temporary srpvfile created.\n");
        if (!rotate_index(dbfile, "new", "old"))
            goto end;

        if (verbose)
            BIO_printf(bio_err, "srpvfile updated.\n");
    }

    ret = (errors != 0);
 end:
    if (errors != 0)
        if (verbose)
            BIO_printf(bio_err, "User errors %d.\n", errors);

    if (verbose)
        BIO_printf(bio_err, "SRP terminating with code %d.\n", ret);
    OPENSSL_free(tofree);
    if (ret)
        ERR_print_errors(bio_err);
    if (randfile)
        app_RAND_write_file(randfile);
    NCONF_free(conf);
    free_index(db);
    OBJ_cleanup();
    return (ret);
}