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; }
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; }