/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include static void echo_off (struct termios *stored_settings) { struct termios new_settings; tcgetattr (0, stored_settings); new_settings = *stored_settings; new_settings.c_lflag &= (~ECHO); tcsetattr (0, TCSANOW, &new_settings); } static void echo_on (struct termios *stored_settings) { tcsetattr (0, TCSANOW, stored_settings); } int mu_ticket_create (mu_ticket_t *pticket, void *owner) { mu_ticket_t ticket; if (pticket == NULL) return MU_ERR_OUT_PTR_NULL; ticket = calloc (1, sizeof (*ticket)); if (ticket == NULL) return ENOMEM; ticket->owner = owner; mu_ticket_ref (ticket); *pticket = ticket; return 0; } int mu_ticket_ref (mu_ticket_t ticket) { if (!ticket) return EINVAL; ticket->refcnt++; return 0; } int mu_ticket_unref (mu_ticket_t ticket) { if (!ticket) return EINVAL; if (ticket->refcnt) ticket->refcnt--; if (ticket->refcnt == 0) { if (ticket->plain) free (ticket->plain); if (ticket->secret) mu_secret_destroy (&ticket->secret); if (ticket->_destroy) ticket->_destroy (ticket); free (ticket); return 0; } return MU_ERR_EXISTS; } void mu_ticket_destroy (mu_ticket_t *pticket) { if (pticket && *pticket && mu_ticket_unref (*pticket) == 0) *pticket = NULL; } int mu_ticket_set_destroy (mu_ticket_t ticket, void (*_destroy) (mu_ticket_t), void *owner) { if (ticket == NULL) return EINVAL; if (ticket->owner != owner) return EACCES; ticket->_destroy = _destroy; return 0; } void * mu_ticket_get_owner (mu_ticket_t ticket) { return (ticket) ? ticket->owner : NULL; } int mu_ticket_set_get_cred (mu_ticket_t ticket, int (*_get_cred) (mu_ticket_t, mu_url_t, const char *, char **, mu_secret_t *), void *owner) { if (ticket == NULL) return EINVAL; if (ticket->owner != owner) return EACCES; ticket->_get_cred = _get_cred; return 0; } int mu_ticket_set_secret (mu_ticket_t ticket, mu_secret_t secret) { if (ticket == NULL) return EINVAL; if (ticket->secret) mu_secret_unref (ticket->secret); mu_secret_ref (secret); ticket->secret = secret; return 0; } int mu_ticket_set_plain (mu_ticket_t ticket, const char *text) { if (ticket == NULL) return EINVAL; if (ticket->plain) free (ticket->plain); ticket->plain = strdup (text); if (!ticket->plain) return ENOMEM; return 0; } int mu_ticket_get_cred (mu_ticket_t ticket, mu_url_t url, const char *challenge, char **pplain, mu_secret_t *psec) { int rc = 0; char arg[256]; if (ticket == NULL || (pplain && psec)) return EINVAL; if (pplain == NULL && psec == NULL) return MU_ERR_OUT_PTR_NULL; if (ticket->_get_cred) { int res = ticket->_get_cred (ticket, url, challenge, pplain, psec); if (res == 0) return res; } if (pplain && ticket->plain) { *pplain = strdup (ticket->plain); if (!*pplain) return ENOMEM; } if (psec && ticket->secret) { mu_secret_ref (ticket->secret); *psec = ticket->secret; return 0; } if (isatty (fileno (stdin))) { struct termios stored_settings; int echo = pplain != NULL; printf ("%s", challenge); fflush (stdout); if (!echo) echo_off (&stored_settings); fgets (arg, sizeof (arg), stdin); if (!echo) { echo_on (&stored_settings); putchar ('\n'); fflush (stdout); } arg [strlen (arg) - 1] = '\0'; /* nuke the trailing line. */ } else return MU_ERR_FAILURE; if (pplain) { *pplain = strdup (arg); if (!*pplain) return ENOMEM; } else rc = mu_secret_create (psec, arg, strlen (arg)); return rc; } void * mu_ticket_get_data (mu_ticket_t ticket) { if (!ticket) return NULL; return ticket->data; } int mu_ticket_set_data (mu_ticket_t ticket, void *data, void *owner) { if (ticket == NULL) return EINVAL; if (ticket->owner != owner) return EACCES; ticket->data = data; return 0; }