static gpgme_error_t gpgsm_cancel(void *engine) { engine_gpgsm_t gpgsm = engine; if(!gpgsm) return gpg_error(GPG_ERR_INV_VALUE); if(gpgsm->status_cb.fd != -1) _gpgme_io_close(gpgsm->status_cb.fd); if(gpgsm->input_cb.fd != -1) _gpgme_io_close(gpgsm->input_cb.fd); if(gpgsm->output_cb.fd != -1) _gpgme_io_close(gpgsm->output_cb.fd); if(gpgsm->message_cb.fd != -1) _gpgme_io_close(gpgsm->message_cb.fd); if(gpgsm->assuan_ctx) { assuan_disconnect(gpgsm->assuan_ctx); gpgsm->assuan_ctx = NULL; } return 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; }
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; }
int ask_user_consent(sc_card_t *card) { int res; struct stat buf; const char *argv[3]; assuan_fd_t noclosefds[2]; assuan_context_t ctx; if ( (card==NULL) || (card->ctx==NULL)) return SC_ERROR_INVALID_ARGUMENTS; get_user_consent_env(card->ctx); res=stat(user_consent_app,&buf); if (res!=0) { /* TODO: check that pinentry file is executable */ sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,"Invalid pinentry application: %s\n",user_consent_app); SC_FUNC_RETURN(card->ctx,SC_LOG_DEBUG_NORMAL,SC_ERROR_INVALID_ARGUMENTS); } argv[0]=user_consent_app; argv[1]=NULL; argv[2]=NULL; noclosefds[0]= fileno(stderr); noclosefds[1]= ASSUAN_INVALID_FD; #ifdef HAVE_ASSUAN_2 res = assuan_new(&ctx); if (res!=0) { sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,"Can't create the User Consent environment: %s\n",_gpg_error(res)); SC_FUNC_RETURN(card->ctx,SC_LOG_DEBUG_NORMAL,SC_ERROR_INVALID_ARGUMENTS); } res = assuan_pipe_connect(ctx,user_consent_app,argv,noclosefds,NULL,NULL,0); #else res = assuan_pipe_connect(&ctx,user_consent_app,argv,0); #endif if (res!=0) { sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,"Can't connect to the User Consent module: %s\n",_gpg_error(res)); res=SC_ERROR_INVALID_ARGUMENTS; /* invalid or not available pinentry */ goto exit; } res = assuan_transact( ctx, "SETDESC Está a punto de realizar una firma electrónica con su clave de FIRMA del DNI electrónico.¿Desea permitir esta operación?", NULL, NULL, NULL, NULL, NULL, NULL); if (res!=0) { sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,"SETDESC: %s\n", _gpg_error(res)); res=SC_ERROR_CARD_CMD_FAILED; /* perhaps should use a better errcode */ goto exit; } res = assuan_transact(ctx,"CONFIRM",NULL,NULL,NULL,NULL,NULL,NULL); #ifdef HAVE_ASSUAN_1 if (res == ASSUAN_Canceled) { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE,"Sign cancelled by user"); res= SC_ERROR_NOT_ALLOWED; goto exit; } #endif if (res) { sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL,"SETERROR: %s\n",_gpg_error(res)); res=SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } else { res=SC_SUCCESS; } exit: #ifdef HAVE_ASSUAN_2 assuan_release(ctx); #else assuan_disconnect(ctx); #endif SC_FUNC_RETURN(card->ctx,SC_LOG_DEBUG_NORMAL,res); }