Beispiel #1
0
int ask_user_auth()
{
  int r;
  const char *argv[3];
  const char *pgmname = PIN_ENTRY; 
  ASSUAN_CONTEXT ctx;
  gchar buf[500];
  gsize buflen = sizeof(buf);
  gchar *buf_conv_ptr = NULL;
  const char *local_charset, *default_charset;
  gsize bytes_read=0, bytes_written=0;  
  gboolean is_utf8;

  memset(buf, 0, buflen);
  default_charset = setlocale(LC_CTYPE, "");

  setlocale(LC_ALL, "");
  bindtextdomain(PACKAGE, "/usr/share/locale");
  textdomain(PACKAGE);

  argv[0] = pgmname;
  argv[1] = NULL;
	
  r = assuan_pipe_connect(&ctx, pgmname, (char **) argv, 0);
  if (r) {
    printf(i18n("Can't connect to the PIN entry module: %s\n"),
	   assuan_strerror((AssuanError) r));
    goto err;
  }
	
  sprintf(buf, i18n("SETDESC Está a punto de realizar una firma electrónica con su clave de FIRMA del DNI electrónico. ¿Desea permitir esta operación?"));
  
  is_utf8 = g_get_charset(&local_charset);  
  buf_conv_ptr = g_convert_with_fallback(buf, buflen, local_charset, "UTF-8", 
					 NULL, &bytes_read, &bytes_written, NULL);
  if(!buf_conv_ptr) {
    printf(i18n("Error converting string to locale charset.\n"));
    goto err;
  }

  r = assuan_transact(ctx, buf_conv_ptr, NULL, NULL, NULL, NULL, NULL, NULL);
  if (r) {
    printf("SETDESC: %s\n", assuan_strerror((AssuanError) r));
    goto err;
  }
  while (1) {
    r = assuan_transact(ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
    if (r == ASSUAN_Canceled) {
      assuan_disconnect(ctx);
      return -2;
    }
    if (r) {
      printf("SETERROR: %s\n", assuan_strerror((AssuanError) r));
      goto err;
    }
    if (r == 0)
      break;
  }

  assuan_disconnect(ctx);	
  return 0;
 err:	
  assuan_disconnect(ctx);
  return -1;
}
Beispiel #2
0
int
pinentry_loop2 (int infd, int outfd)
{
  int rc;
  int filedes[2];
  ASSUAN_CONTEXT ctx;

  /* Extra check to make sure we have dropped privs. */
#ifndef HAVE_DOSISH_SYSTEM
  if (getuid() != geteuid())
    abort ();
#endif

  /* For now we use a simple pipe based server so that we can work
     from scripts.  We will later add options to run as a daemon and
     wait for requests on a Unix domain socket.  */
  filedes[0] = infd;
  filedes[1] = outfd;
  rc = assuan_init_pipe_server (&ctx, filedes);
  if (rc)
    {
      fprintf (stderr, "%s: failed to initialize the server: %s\n",
               this_pgmname, assuan_strerror(rc));
      return -1;
    }
  rc = register_commands (ctx);
  if (rc)
    {
      fprintf (stderr, "%s: failed to the register commands with Assuan: %s\n",
               this_pgmname, assuan_strerror(rc));
      return -1;
    }

  assuan_register_option_handler (ctx, option_handler);
#if 0
  assuan_set_log_stream (ctx, stderr);
#endif
  
  for (;;)
    {
      rc = assuan_accept (ctx);
      if (rc == -1)
          break;
      else if (rc)
        {
          fprintf (stderr, "%s: Assuan accept problem: %s\n",
                   this_pgmname, assuan_strerror (rc));
          break;
        }
      
      rc = assuan_process (ctx);
      if (rc)
        {
          fprintf (stderr, "%s: Assuan processing failed: %s\n",
                   this_pgmname, assuan_strerror (rc));
          continue;
        }
    }

  assuan_deinit_server (ctx);
  return 0;
}
int ask_and_verify_pin_code(struct sc_pkcs15_card *p15card,
			    struct sc_pkcs15_object *pin)
{
	int r;
	size_t len;
	const char *argv[3];
	const char *pgmname = PIN_ENTRY;
	ASSUAN_CONTEXT ctx;
	char buf[500];
	char errtext[100];
	struct entry_parm_s parm;
	struct sc_pkcs15_pin_info *pinfo = (struct sc_pkcs15_pin_info *) pin->data;
	
	argv[0] = pgmname;
	argv[1] = NULL;
	
	r = assuan_pipe_connect(&ctx, pgmname, (char **) argv, NULL);
	if (r) {
		printf("Can't connect to the PIN entry module: %s\n",
		       assuan_strerror((AssuanError) r));
		goto err;
	}
	sprintf(buf, "SETDESC Enter PIN [%s] for digital signing  ", pin->label);
	r = assuan_transact(ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
	if (r) {
		printf("SETDESC: %s\n", assuan_strerror((AssuanError) r));
		goto err;
	}
	errtext[0] = 0;
	while (1) {
		if (errtext[0]) {
			sprintf(buf, "SETERROR %s", errtext);
			r = assuan_transact(ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
			errtext[0] = 0;
		}
		parm.lines = 0;
		parm.size = sizeof(buf);
		parm.buffer = buf;
		r = assuan_transact(ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
		if (r == ASSUAN_Canceled) {
			assuan_disconnect(ctx);
			return -2;
		}
		if (r) {
			printf("GETPIN: %s\n", assuan_strerror((AssuanError) r));
			goto err;
		}
		len = strlen(buf);
		if (len < pinfo->min_length) {
			sprintf(errtext, "PIN code too short, min. %lu digits", (unsigned long) pinfo->min_length);
			continue;
		}
		if (len > pinfo->max_length) {
			sprintf(errtext, "PIN code too long, max. %lu digits", (unsigned long) pinfo->max_length);
			continue;
		}
		r = sc_pkcs15_verify_pin(p15card, pinfo, (const u8 *) buf, strlen(buf));
		switch (r) {
		case SC_ERROR_PIN_CODE_INCORRECT:
			sprintf(errtext, "PIN code incorrect (%d %s left)",
			       pinfo->tries_left, pinfo->tries_left == 1 ?
			       "try" : "tries");
			break;
		case 0:
			break;
		default:
			goto err;
		}
		if (r == 0)
			break;
	}

	assuan_disconnect(ctx);	
	return 0;
err:	
	assuan_disconnect(ctx);
	return -1;
}
/* Make a connection to the Unix domain socket NAME and return a new
   Assuan context in CTX.  SERVER_PID is currently not used but may
   become handy in the future.  With flags set to 1 sendmsg and
   recvmesg are used. */
assuan_error_t
assuan_socket_connect_ext(assuan_context_t *r_ctx,
                          const char *name, pid_t server_pid,
                          unsigned int flags)
{
    static struct assuan_io io = { _assuan_simple_read,
               _assuan_simple_write
    };

    assuan_error_t err;
    assuan_context_t ctx;
    int fd;
    struct sockaddr_un srvr_addr;
    size_t len;
    const char *s;

    if(!r_ctx || !name)
        return _assuan_error(ASSUAN_Invalid_Value);
    *r_ctx = NULL;

    /* We require that the name starts with a slash, so that we
       eventually can reuse this function for other socket types.  To
       make things easier we allow an optional dirver prefix.  */
    s = name;
    if(*s && s[1] == ':')
        s += 2;
    if(*s != DIRSEP_C && *s != '/')
        return _assuan_error(ASSUAN_Invalid_Value);

    if(strlen(name) + 1 >= sizeof srvr_addr.sun_path)
        return _assuan_error(ASSUAN_Invalid_Value);

    err = _assuan_new_context(&ctx);
    if(err)
        return err;
    ctx->deinit_handler = ((flags & 1)) ? _assuan_uds_deinit :  do_deinit;
    ctx->finish_handler = do_finish;

    fd = _assuan_sock_new(PF_LOCAL, SOCK_STREAM, 0);
    if(fd == -1)
    {
        _assuan_log_printf("can't create socket: %s\n", strerror(errno));
        _assuan_release_context(ctx);
        return _assuan_error(ASSUAN_General_Error);
    }

    memset(&srvr_addr, 0, sizeof srvr_addr);
    srvr_addr.sun_family = AF_LOCAL;
    strncpy(srvr_addr.sun_path, name, sizeof(srvr_addr.sun_path) - 1);
    srvr_addr.sun_path[sizeof(srvr_addr.sun_path) - 1] = 0;
    len = SUN_LEN(&srvr_addr);


    if(_assuan_sock_connect(fd, (struct sockaddr *) &srvr_addr, len) == -1)
    {
        _assuan_log_printf("can't connect to `%s': %s\n",
                           name, strerror(errno));
        _assuan_release_context(ctx);
        _assuan_close(fd);
        return _assuan_error(ASSUAN_Connect_Failed);
    }

    ctx->inbound.fd = fd;
    ctx->outbound.fd = fd;
    ctx->io = &io;
    if((flags & 1))
        _assuan_init_uds_io(ctx);

    /* initial handshake */
    {
        int okay, off;

        err = _assuan_read_from_server(ctx, &okay, &off);
        if(err)
            _assuan_log_printf("can't connect to server: %s\n",
                               assuan_strerror(err));
        else if(okay != 1)
        {
            /*LOG ("can't connect to server: `");*/
            _assuan_log_sanitized_string(ctx->inbound.line);
            fprintf(assuan_get_assuan_log_stream(), "'\n");
            err = _assuan_error(ASSUAN_Connect_Failed);
        }
    }

    if(err)
    {
        assuan_disconnect(ctx);
    }
    else
        *r_ctx = ctx;
    return 0;
}