diff options
Diffstat (limited to 'pith')
-rw-r--r-- | pith/conftype.h | 10 | ||||
-rw-r--r-- | pith/filter.c | 209 | ||||
-rw-r--r-- | pith/mimedesc.c | 2 | ||||
-rw-r--r-- | pith/pine.hlp | 56 | ||||
-rw-r--r-- | pith/reply.c | 2 | ||||
-rw-r--r-- | pith/send.c | 5 | ||||
-rw-r--r-- | pith/smime.c | 21 | ||||
-rw-r--r-- | pith/smkeys.c | 132 | ||||
-rw-r--r-- | pith/smkeys.h | 2 |
9 files changed, 324 insertions, 115 deletions
diff --git a/pith/conftype.h b/pith/conftype.h index 8ba7941c..11bf778f 100644 --- a/pith/conftype.h +++ b/pith/conftype.h @@ -676,6 +676,9 @@ typedef enum {Public, Private, CACert} WhichCerts; typedef struct certdata { unsigned deleted:1; /* certificate is marked deleted */ unsigned renew:1; /* we must renew this list, set at top cert */ + char *date_from; /* date from which certificate is valid */ + char *date_to; /* date certificate expires */ + char *md5; /* MD5 Hash */ } CertData; typedef struct certlist { @@ -740,8 +743,11 @@ typedef struct smime_stuff { : ((X) == Private ? ".key" \ : ((X) == CACert ? ".crt" : "")))) -#define DELETEDCERT(X) ((X)->data.deleted) -#define RENEWCERT(X) ((X)->data.renew) +#define DELETEDCERT(X) ((X)->data.deleted) +#define RENEWCERT(X) ((X)->data.renew) +#define DATEFROMCERT(X) ((X)->data.date_from) +#define DATETOCERT(X) ((X)->data.date_to) +#define MD5CERT(X) ((X)->data.md5) #endif /* SMIME */ diff --git a/pith/filter.c b/pith/filter.c index c60416b1..d1848f87 100644 --- a/pith/filter.c +++ b/pith/filter.c @@ -2803,8 +2803,10 @@ typedef struct handler_s { */ typedef struct _element_properties { char *element; + size_t len; int (*handler)(HANDLER_S *, int, int); unsigned blocklevel:1; + unsigned alternate:1; } ELPROP_S; /* @@ -3549,96 +3551,96 @@ static struct html_entities { * Table of supported elements and corresponding handlers */ static ELPROP_S html_element_table[] = { - {"HTML"}, /* HTML ignore if seen? */ - {"HEAD", html_head}, /* slurp until <BODY> ? */ - {"TITLE", html_title}, /* Document Title */ - {"BASE", html_base}, /* HREF base */ - {"BODY", html_body}, /* HTML BODY */ - {"A", html_a}, /* Anchor */ - {"ABBR", html_abbr}, /* Abbreviation */ - {"IMG", html_img}, /* Image */ - {"MAP", html_map}, /* Image Map */ - {"AREA", html_area}, /* Image Map Area */ - {"HR", html_hr, 1}, /* Horizontal Rule */ - {"BR", html_br}, /* Line Break */ - {"P", html_p, 1}, /* Paragraph */ - {"OL", html_ol, 1}, /* Ordered List */ - {"UL", html_ul, 1}, /* Unordered List */ - {"MENU", html_menu}, /* Menu List */ - {"DIR", html_dir}, /* Directory List */ - {"LI", html_li}, /* ... List Item */ - {"DL", html_dl, 1}, /* Definition List */ - {"DT", html_dt}, /* ... Def. Term */ - {"DD", html_dd}, /* ... Def. Definition */ - {"I", html_i}, /* Italic Text */ - {"EM", html_em}, /* Typographic Emphasis */ - {"STRONG", html_strong}, /* STRONG Typo Emphasis */ - {"VAR", html_i}, /* Variable Name */ - {"B", html_b}, /* Bold Text */ - {"U", html_u}, /* Underline Text */ - {"S", html_s}, /* Strike-Through Text */ - {"STRIKE", html_s}, /* Strike-Through Text */ - {"BIG", html_big}, /* Big Font Text */ - {"SMALL", html_small}, /* Small Font Text */ - {"FONT", html_font}, /* Font display directives */ - {"BLOCKQUOTE", html_blockquote, 1}, /* Blockquote */ - {"ADDRESS", html_address, 1}, /* Address */ - {"CENTER", html_center}, /* Centered Text v3.2 */ - {"DIV", html_div, 1}, /* Document Division 3.2 */ - {"SPAN", html_span}, /* Text Span */ - {"H1", html_h1, 1}, /* Headings... */ - {"H2", html_h2, 1}, - {"H3", html_h3,1}, - {"H4", html_h4, 1}, - {"H5", html_h5, 1}, - {"H6", html_h6, 1}, - {"PRE", html_pre, 1}, /* Preformatted Text */ - {"KBD", html_kbd}, /* Keyboard Input (NO OP) */ - {"DFN", html_dfn}, /* Definition (NO OP) */ - {"VAR", html_var}, /* Variable (NO OP) */ - {"TT", html_tt}, /* Typetype (NO OP) */ - {"SAMP", html_samp}, /* Sample Text (NO OP) */ - {"CITE", html_cite}, /* Citation (NO OP) */ - {"CODE", html_code}, /* Code Text (NO OP) */ - {"INS", html_ins}, /* Text Inseted (NO OP) */ - {"DEL", html_del}, /* Text Deleted (NO OP) */ - {"SUP", html_sup}, /* Text Superscript (NO OP) */ - {"SUB", html_sub}, /* Text Superscript (NO OP) */ - {"STYLE", html_style}, /* CSS Definitions */ + {"HTML", 4}, /* HTML ignore if seen? */ + {"HEAD", 4, html_head}, /* slurp until <BODY> ? */ + {"TITLE", 5, html_title}, /* Document Title */ + {"BASE", 4, html_base}, /* HREF base */ + {"BODY", 4, html_body}, /* HTML BODY */ + {"A", 1, html_a}, /* Anchor */ + {"ABBR", 4, html_abbr}, /* Abbreviation */ + {"IMG", 3, html_img}, /* Image */ + {"MAP", 3, html_map}, /* Image Map */ + {"AREA", 4, html_area}, /* Image Map Area */ + {"HR", 2, html_hr, 1, 1}, /* Horizontal Rule */ + {"BR", 2, html_br, 0, 1}, /* Line Break */ + {"P", 1, html_p, 1}, /* Paragraph */ + {"OL", 2, html_ol, 1}, /* Ordered List */ + {"UL", 2, html_ul, 1}, /* Unordered List */ + {"MENU", 4, html_menu}, /* Menu List */ + {"DIR", 3, html_dir}, /* Directory List */ + {"LI", 2, html_li}, /* ... List Item */ + {"DL", 2, html_dl, 1}, /* Definition List */ + {"DT", 2, html_dt}, /* ... Def. Term */ + {"DD", 2, html_dd}, /* ... Def. Definition */ + {"I", 1, html_i}, /* Italic Text */ + {"EM", 2, html_em}, /* Typographic Emphasis */ + {"STRONG", 6, html_strong}, /* STRONG Typo Emphasis */ + {"VAR", 3, html_i}, /* Variable Name */ + {"B", 1, html_b}, /* Bold Text */ + {"U", 1, html_u}, /* Underline Text */ + {"S", 1, html_s}, /* Strike-Through Text */ + {"STRIKE", 6, html_s}, /* Strike-Through Text */ + {"BIG", 3, html_big}, /* Big Font Text */ + {"SMALL", 5, html_small}, /* Small Font Text */ + {"FONT", 4, html_font}, /* Font display directives */ + {"BLOCKQUOTE", 10, html_blockquote, 1}, /* Blockquote */ + {"ADDRESS", 7, html_address, 1}, /* Address */ + {"CENTER", 6, html_center}, /* Centered Text v3.2 */ + {"DIV", 3, html_div, 1}, /* Document Division 3.2 */ + {"SPAN", 4, html_span}, /* Text Span */ + {"H1", 2, html_h1, 1}, /* Headings... */ + {"H2", 2, html_h2, 1}, + {"H3", 2, html_h3,1}, + {"H4", 2, html_h4, 1}, + {"H5", 2, html_h5, 1}, + {"H6", 2, html_h6, 1}, + {"PRE", 3, html_pre, 1}, /* Preformatted Text */ + {"KBD", 3, html_kbd}, /* Keyboard Input (NO OP) */ + {"DFN", 3, html_dfn}, /* Definition (NO OP) */ + {"VAR", 3, html_var}, /* Variable (NO OP) */ + {"TT", 2, html_tt}, /* Typetype (NO OP) */ + {"SAMP", 4, html_samp}, /* Sample Text (NO OP) */ + {"CITE", 4, html_cite}, /* Citation (NO OP) */ + {"CODE", 4, html_code}, /* Code Text (NO OP) */ + {"INS", 3, html_ins}, /* Text Inseted (NO OP) */ + {"DEL", 3, html_del}, /* Text Deleted (NO OP) */ + {"SUP", 3, html_sup}, /* Text Superscript (NO OP) */ + {"SUB", 3, html_sub}, /* Text Superscript (NO OP) */ + {"STYLE", 5, html_style}, /* CSS Definitions */ /*----- Handlers below UNIMPLEMENTED (and won't until later) -----*/ - {"FORM", html_form, 1}, /* form within a document */ - {"INPUT", html_input}, /* One input field, options */ - {"BUTTON", html_button}, /* Push Button */ - {"OPTION", html_option}, /* One option within Select */ - {"OPTION", html_optgroup}, /* Option Group Definition */ - {"SELECT", html_select}, /* Selection from a set */ - {"TEXTAREA", html_textarea}, /* A multi-line input field */ - {"LABEL", html_label}, /* Control Label */ - {"FIELDSET", html_fieldset, 1}, /* Fieldset Control Group */ + {"FORM", 4, html_form, 1}, /* form within a document */ + {"INPUT", 5, html_input}, /* One input field, options */ + {"BUTTON", 6, html_button}, /* Push Button */ + {"OPTION", 6, html_option}, /* One option within Select */ + {"OPTION", 6, html_optgroup}, /* Option Group Definition */ + {"SELECT", 6, html_select}, /* Selection from a set */ + {"TEXTAREA", 8, html_textarea}, /* A multi-line input field */ + {"LABEL", 5, html_label}, /* Control Label */ + {"FIELDSET", 8, html_fieldset, 1}, /* Fieldset Control Group */ /*----- Handlers below NEVER TO BE IMPLEMENTED -----*/ - {"SCRIPT", html_script}, /* Embedded scripting statements */ - {"APPLET", NULL}, /* Embedded applet statements */ - {"OBJECT", NULL}, /* Embedded object statements */ - {"LINK", NULL}, /* References to external data */ - {"PARAM", NULL}, /* Applet/Object parameters */ + {"SCRIPT", 6, html_script}, /* Embedded scripting statements */ + {"APPLET", 6, NULL}, /* Embedded applet statements */ + {"OBJECT", 6, NULL}, /* Embedded object statements */ + {"LINK", 4, NULL}, /* References to external data */ + {"PARAM", 5, NULL}, /* Applet/Object parameters */ /*----- Handlers below provide limited support for RFC 1942 Tables -----*/ - {"TABLE", html_table, 1}, /* Table */ - {"CAPTION", html_caption}, /* Table Caption */ - {"TR", html_tr}, /* Table Table Row */ - {"TD", html_td}, /* Table Table Data */ - {"TH", html_th}, /* Table Table Head */ - {"THEAD", html_thead}, /* Table Table Head */ - {"TBODY", html_tbody}, /* Table Table Body */ - {"TFOOT", html_tfoot}, /* Table Table Foot */ - {"COL", html_col}, /* Table Column Attibutes */ - {"COLGROUP", html_colgroup}, /* Table Column Group Attibutes */ - - {NULL, NULL} + {"TABLE", 5, html_table, 1}, /* Table */ + {"CAPTION", 7, html_caption}, /* Table Caption */ + {"TR", 2, html_tr}, /* Table Table Row */ + {"TD", 2, html_td}, /* Table Table Data */ + {"TH", 2, html_th}, /* Table Table Head */ + {"THEAD", 5, html_thead}, /* Table Table Head */ + {"TBODY", 5, html_tbody}, /* Table Table Body */ + {"TFOOT", 5, html_tfoot}, /* Table Table Foot */ + {"COL", 3, html_col}, /* Table Column Attibutes */ + {"COLGROUP", 8, html_colgroup}, /* Table Column Group Attibutes */ + + {NULL, 0, NULL} }; @@ -3646,15 +3648,15 @@ static ELPROP_S html_element_table[] = { * Table of supported RSS 2.0 elements */ static ELPROP_S rss_element_table[] = { - {"RSS", rss_rss}, /* RSS 2.0 version */ - {"CHANNEL", rss_channel}, /* RSS 2.0 Channel */ - {"TITLE", rss_title}, /* RSS 2.0 Title */ - {"IMAGE", rss_image}, /* RSS 2.0 Channel Image */ - {"LINK", rss_link}, /* RSS 2.0 Channel/Item Link */ - {"DESCRIPTION", rss_description}, /* RSS 2.0 Channel/Item Description */ - {"ITEM", rss_item}, /* RSS 2.0 Channel ITEM */ - {"TTL", rss_ttl}, /* RSS 2.0 Item TTL */ - {NULL, NULL} + {"RSS", 3, rss_rss}, /* RSS 2.0 version */ + {"CHANNEL", 7, rss_channel}, /* RSS 2.0 Channel */ + {"TITLE", 5, rss_title}, /* RSS 2.0 Title */ + {"IMAGE", 5, rss_image}, /* RSS 2.0 Channel Image */ + {"LINK", 4, rss_link}, /* RSS 2.0 Channel/Item Link */ + {"DESCRIPTION", 11, rss_description}, /* RSS 2.0 Channel/Item Description */ + {"ITEM", 4, rss_item}, /* RSS 2.0 Channel ITEM */ + {"TTL", 3, rss_ttl}, /* RSS 2.0 Item TTL */ + {NULL, 0, NULL} }; @@ -7167,9 +7169,14 @@ ELPROP_S * element_properties(FILTER_S *fd, char *el_name) { register ELPROP_S *el_table = ELEMENTS(fd); + size_t len_name = strlen(el_name); for(; el_table->element; el_table++) - if(!strucmp(el_name, el_table->element)) + if(!strucmp(el_name, el_table->element) + || (el_table->alternate + && len_name == el_table->len + 1 + && el_name[el_table->len] == '/' + && !struncmp(el_name, el_table->element, el_table->len))) return(el_table); return(NULL); @@ -7427,6 +7434,24 @@ html_element_collector(FILTER_S *fd, int ch) if(!ED(fd)->hit_equal) ED(fd)->hit_equal = (ch == '='); } + else if(ch == '/' && ED(fd)->len && !ED(fd)->element){ + ELPROP_S *ep; + ep = element_properties(fd, ED(fd)->buf); + if(ep){ + if(!ep->alternate) + ED(fd)->badform = 1; + else{ + if(ED(fd)->len < ((ED(fd)->element || !ED(fd)->hit_equal) + ? HTML_BUF_LEN:MAX_ELEMENT)){ + ED(fd)->buf[(ED(fd)->len)++] = ch; /* add this exception */ + } + else + ED(fd)->overrun = 1; + } + } + else + ED(fd)->badform = 1; + } else ED(fd)->badform = 1; /* unrecognized data?? */ diff --git a/pith/mimedesc.c b/pith/mimedesc.c index 8a1d7f7d..67d52ae6 100644 --- a/pith/mimedesc.c +++ b/pith/mimedesc.c @@ -277,7 +277,7 @@ describe_mime(struct mail_bodystruct *body, char *prefix, int num, snprintf(a->number, ll, "%s%d",prefix, num); a->number[ll-1] = '\0'; (a+1)->description = NULL; - if(body->type == TYPEMESSAGE && body->encoding <= ENCBINARY + if(body->type == TYPEMESSAGE && body->encoding <= ENCBASE64 && body->subtype && strucmp(body->subtype, "rfc822") == 0){ body = body->nested.msg->body; snprintf(numx, sizeof(numx), "%.*s%d.", sizeof(numx)-20, prefix, num); diff --git a/pith/pine.hlp b/pith/pine.hlp index 90be0132..cb0a6d63 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any reasonable place to be called from. Dummy change to get revision in pine.hlp ============= h_revision ================= -Alpine Commit 64 2014-05-31 21:36:57 +Alpine Commit 65 2014-06-20 23:23:15 ============= h_news ================= <HTML> <HEAD> @@ -205,6 +205,10 @@ Additions include: <LI> S/MIME: Forwarding a message will include the signed part as part of the text and not as a multipart message, just as the reply command does. + <LI> HTML: Style tag in body of html message causes Alpine to not write + its content until a new </style> + <LI> HTML: <BR>, <BR />, and <BR/> are considered + the same inline tag; the same is valid for the <HR> tag. <LI> Add support to selective expunge through a subcommand of the select-apply commands. Read more in the <A HREF="h_index_cmd_expunge">help</A> for the expunge command. @@ -296,6 +300,10 @@ Bugs that have been addressed include: an index was based on scores that needed information from a remote addressbook in the same server as the folder opened. Reported by Peter Koellner. + <LI> Crash in message/rfc822 attachments encoded in base64. + <LI> Postponed messages whose content-type is text/html, text/enriched and + text/richtext are sent with that content-type, even though, after + resuming composition, Alpine had changed its type to text/plain. <LI> Alpine cannot handle correctly some characters in the Windows-1256 character set, which might lead to a crash or a corruption in the screen. Work was done to contain the bug. A more complete fix will @@ -35154,8 +35162,20 @@ and private information about your key, with the <B>B</B> and UNIX Alpine only. <P> -This screen allows you to manage your public certificates. Available commands and -a short description of what they do follows. +This screen allows you to manage your public certificates. +<P> +The format of this screen is as follows. There are five fields: The +leftmost field is normally empty, but it could contain the letter +"D" to indicate that that certificate has been marked for +deletion. The next field is the e-mail address of the owner of the +certificate, shown in its entirety. The third field is the first day of +validity for that certificate; the fourth field in the last day that that +certificate is valid, and the fifth field is what can be displayed of the +MD5 hash of the certificate. You can use any of the last three fields to +distinguish between two certificates for the same owner. +<P> +Available commands in this screen and a short description of what they +do follows. <UL> <LI> <B>I</B> Imports a public certificate to this collection. <LI> <B>V</B> View information about a certificate such as the name of the person the @@ -35189,8 +35209,20 @@ All commands provide feedback to let you know about their success or failure. UNIX Alpine only. <P> -This screen allows you to manage your private key. Available commands and -a short description of what they do follows. +This screen allows you to manage your private key. +<P> +The format of this screen is as follows. There are five fields: The +leftmost field is normally empty, but it could contain the letter +"D" to indicate that that certificate has been marked for +deletion. The next field is the e-mail address of the owner of the +certificate, shown in its entirety. The third field is the first day of +validity for that certificate; the fourth field in the last day that that +certificate is valid, and the fifth field is what can be displayed of the +MD5 hash of the public certificate corresponding to this private key. You +can use any of the last three fields to distinguish between two +certificates for the same owner. +<P> +Available commands and a short description of what they do follows. <UL> <LI> <B>I</B> Imports a new public key to this collection. <LI> <B>V</B> View information about the public certificate corresponding to this @@ -35225,7 +35257,19 @@ All commands provide feedback to let you know about their success or failure. UNIX Alpine only. <P> This screen allows you to manage your collection of certificates that you -trust. Available commands and a short description of what they do follows. +trust. +<P> +The format of this screen is as follows. There are five fields: The +leftmost field is normally empty, but it could contain the letter +"D" to indicate that that certificate has been marked for +deletion. The next field is the e-mail address of the owner of the +certificate, shown in its entirety. The third field is the first day of +validity for that certificate; the fourth field in the last day that that +certificate is valid, and the fifth field is what can be displayed of the +MD5 hash of the certificate. You can use any of the last three fields to +distinguish between two certificates for the same owner. +<P> +Available commands and a short description of what they do follows. <UL> <LI> <B>I</B> Imports a trusted certificate to this collection. This is done by reading the certificate and validating it. Once a certificate diff --git a/pith/reply.c b/pith/reply.c index 2a8ab158..ec8293db 100644 --- a/pith/reply.c +++ b/pith/reply.c @@ -46,9 +46,7 @@ static char rcsid[] = "$Id: reply.c 1074 2008-06-04 00:08:43Z hubert@u.washingto #include "../pith/ablookup.h" #include "../pith/mailcmd.h" #include "../pith/margin.h" -#ifdef SMIME #include "../pith/smime.h" -#endif /* SMIME */ /* diff --git a/pith/send.c b/pith/send.c index b01ff7e5..e829d19c 100644 --- a/pith/send.c +++ b/pith/send.c @@ -890,7 +890,10 @@ redraft_work(MAILSTREAM **streamp, long int cont_msg, ENVELOPE **outgoing, else{ *body = mail_newbody(); (*body)->type = TYPETEXT; - if(b->subtype) + if(b->subtype /* these types are transformed to text/plain */ + && strucmp(b->subtype, "richtext") + && strucmp(b->subtype, "enriched") + && strucmp(b->subtype, "html")) (*body)->subtype = cpystr(b->subtype); if((charset = parameter_val(b->parameter,"charset")) != NULL){ diff --git a/pith/smime.c b/pith/smime.c index 44cc1955..f29e37df 100644 --- a/pith/smime.c +++ b/pith/smime.c @@ -903,6 +903,8 @@ CertList * certlist_from_personal_certs(PERSONAL_CERT *pc) { CertList *cl; + X509 *x; + char buf[MAXPATH]; if(pc == NULL) return NULL; @@ -910,12 +912,21 @@ certlist_from_personal_certs(PERSONAL_CERT *pc) cl = fs_get(sizeof(CertList)); memset((void *)cl, 0, sizeof(CertList)); cl->name = cpystr(pc->name); + x = get_cert_for(pc->name, Public); + if(x){ + if(x->cert_info){ + cl->data.date_from = smime_get_date(x->cert_info->validity->notBefore); + cl->data.date_to = smime_get_date(x->cert_info->validity->notAfter); + get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL); + cl->data.md5 = cpystr(buf); + } + X509_free(x); + } cl->next = certlist_from_personal_certs(pc->next); return cl; } - void renew_cert_data(CertList **data, WhichCerts ctype) { @@ -928,8 +939,10 @@ renew_cert_data(CertList **data, WhichCerts ctype) free_personal_certs(&pc); setup_privatekey_storage(); *data = certlist_from_personal_certs((PERSONAL_CERT *)ps_global->smime->personal_certs); - if(data && *data) + if(data && *data){ + resort_certificates(data, ctype); RENEWCERT(*data) = 0; + } ps_global->smime->privatecertlist = *data; } if(ps_global->smime->privatecertlist) @@ -948,8 +961,10 @@ renew_cert_data(CertList **data, WhichCerts ctype) add_certs_in_dir(lookup, PATHCERTDIR(ctype), EXTCERT(ctype), data); else /* if(SMHOLDERTYPE(ctype) == Container) */ *data = mem_to_certlist(CONTENTCERTLIST(ctype), ctype); - if(data && *data) + if(data && *data){ + resort_certificates(data, ctype); RENEWCERT(*data) = 0; + } if(ctype == Public) ps_global->smime->publiccertlist = *data; else diff --git a/pith/smkeys.c b/pith/smkeys.c index 18ed6f1b..437cba6f 100644 --- a/pith/smkeys.c +++ b/pith/smkeys.c @@ -32,6 +32,7 @@ static char rcsid[] = "$Id: smkeys.c 1266 2009-07-14 18:39:12Z hubert@u.washingt #include "../pith/busy.h" #include "../pith/osdep/lstcmpnt.h" #include "../pith/util.h" +#include "../pith/mailindx.h" #include "smkeys.h" #ifdef APPLEKEYCHAIN @@ -45,6 +46,57 @@ static char rcsid[] = "$Id: smkeys.c 1266 2009-07-14 18:39:12Z hubert@u.washingt /* internal prototypes */ static char *emailstrclean(char *string); static int mem_add_extra_cacerts(char *contents, X509_LOOKUP *lookup); +int compare_certs(const void *data1, const void *data2); + +int +compare_certs(const void *data1, const void *data2) +{ + int rv; + char *s; + + CertList *cl1 = *(CertList **) data1; + CertList *cl2 = *(CertList **) data2; + + if((s = strchr(cl1->name, '@')) != NULL) + *s = '\0'; + + if((s = strchr(cl2->name, '@')) != NULL) + *s = '\0'; + + if((rv = strucmp(cl1->name, cl2->name)) == 0) + rv = strucmp(cl1->name + strlen(cl1->name) + 1, cl2->name + strlen(cl2->name) + 1); + cl1->name[strlen(cl1->name)] = '@'; + cl2->name[strlen(cl2->name)] = '@'; + return rv; +} + +void +resort_certificates(CertList **data, WhichCerts ctype) +{ + int i, j; + CertList *cl = *data; + CertList **cll; + char *s, *t; + + for(i = 0; cl; cl = cl->next, i++) + if(ctype != Private){ /* ctype == Public or ctype == CACerts */ + for(t = s = cl->name; t = strstr(s, ".crt"); s = t+1); + if (s) *(s-1) = '\0'; + } + j = i; + cll = fs_get(i*sizeof(CertList *)); + for(cl = *data, i = 0; cl; cl = cl->next, i++) + cll[i] = cl; + qsort((void *)cll, j, sizeof(CertList *), compare_certs); + for(i = 0; i < j - 1; i++){ + cll[i]->next = cll[i+1]; + if(ctype != Private) + cll[i]->name[strlen(cll[i]->name)]= '.'; /* restore ".crt" part */ + } + cll[j-1]->next = NULL; + *data = cll[0]; +} + /* given a certificate and an email address, add the * extension and md5 key to the name. return an allocated @@ -56,11 +108,9 @@ smime_name(char *email, X509 *x, WhichCerts ctype) char bufx[256]; char *rv; - snprintf(bufx, sizeof(bufx), "%08lx",X509_subject_name_hash(x)); - rv = cpystr(bufx); -// get_fingerprint(x, EVP_md5(), bufx, sizeof(bufx), NULL); -// rv = fs_get(strlen(email) + 4 + 2 + strlen(bufx) + 1); -// sprintf(rv, "%s%s.%s", email, EXTCERT(ctype), bufx); + get_fingerprint(x, EVP_md5(), bufx, sizeof(bufx), NULL); + rv = fs_get(strlen(email) + 4 + 2 + strlen(bufx) + 1); + sprintf(rv, "%s%s.%s", email, EXTCERT(ctype), bufx); return rv; } @@ -128,8 +178,48 @@ emailstrclean(char *string) } +char * +smime_get_date(ASN1_GENERALIZEDTIME *tm) +{ + BIO *mb = BIO_new(BIO_s_mem()); + char iobuf[4096]; + char date[MAILTMPLEN]; + char buf[MAILTMPLEN]; + char *m, *d, *t, *y, *z; + + (void) BIO_reset(mb); + ASN1_UTCTIME_print(mb, tm); + (void) BIO_flush(mb); + BIO_read(mb, iobuf, sizeof(iobuf)); + + /* openssl returns the date in the format: + * "MONTH (as name) DAY (as number) TIME(hh:mm:ss) YEAR GMT" + */ + m = iobuf; + d = strchr(iobuf, ' '); + *d++ = '\0'; + while(*d == ' ') d++; + t = strchr(d+1, ' '); + *t++ = '\0'; + while(*t == ' ') t++; + y = strchr(t+1, ' '); + *y++ = '\0'; + while(*y == ' ') y++; + z = strchr(y+1, ' '); + *z++ = '\0'; + while(*z == ' ') z++; + + snprintf(date, sizeof(date), "%s %s %s %s (%s)", d, m, y, t, z); + date[sizeof(date)-1] = '\0'; + date_str((char *) date, iSDateS1, 1, buf, sizeof(buf), 0); + if(buf[strlen(buf) - 1] == '!') + buf[strlen(buf) - 1] = '\0'; + + return cpystr(buf); +} + /* - * Add a lookup for each "*.crt" file in the given directory. + * Add a lookup for each "*.crt*" file in the given directory. */ int add_certs_in_dir(X509_LOOKUP *lookup, char *path, char *ext, CertList **cdata) @@ -150,14 +240,29 @@ add_certs_in_dir(X509_LOOKUP *lookup, char *path, char *ext, CertList **cdata) ret = -1; } else { if(cdata){ + BIO *in; + X509 *x; + cert = fs_get(sizeof(CertList)); memset((void *)cert, 0, sizeof(CertList)); cert->name = cpystr(d->d_name); + /* read buf into a bio and fill the CertData structure */ + if((in = BIO_new_file(buf, "r"))!=0){ + x = PEM_read_bio_X509(in, NULL, NULL, NULL); + if(x && x->cert_info){ + cert->data.date_from = smime_get_date(x->cert_info->validity->notBefore); + cert->data.date_to = smime_get_date(x->cert_info->validity->notAfter); + get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL); + cert->data.md5 = cpystr(buf); + X509_free(x); + } + BIO_free(in); + } if(*cdata == NULL) *cdata = cert; else{ for (cl = *cdata; cl && cl->next; cl = cl->next); - cl->next = cert; + cl->next = cert; } } @@ -211,6 +316,7 @@ get_ca_store(void) X509_STORE_free(store); return NULL; } + resort_certificates(&ps_global->smime->cacertlist, CACert); } if(!(lookup=X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))){ @@ -966,13 +1072,23 @@ void free_certlist(CertList **cl) { if(cl && *cl){ - free_certlist(&(*cl)->next); + if((*cl)->data.date_from) + fs_give((void **) &(*cl)->data.date_from); + + if((*cl)->data.date_to) + fs_give((void **) &(*cl)->data.date_to); + + if((*cl)->data.md5) + fs_give((void **) &(*cl)->data.md5); + if((*cl)->name) fs_give((void **) &(*cl)->name); if((*cl)->x509_cert) X509_free((X509 *) (*cl)->x509_cert); + free_certlist(&(*cl)->next); + fs_give((void **) cl); } } diff --git a/pith/smkeys.h b/pith/smkeys.h index 0fe8faad..5214a369 100644 --- a/pith/smkeys.h +++ b/pith/smkeys.h @@ -61,6 +61,8 @@ void get_fingerprint(X509 *cert, const EVP_MD *type, char *buf, size_t ma int certlist_to_file(char *filename, CertList *certlist); int load_cert_for_key(char *pathdir, EVP_PKEY *pkey, char **certfile, X509 **pcert); char *smime_name(char *email, X509 *x, WhichCerts ctype); +char *smime_get_date(ASN1_GENERALIZEDTIME *tm); +void resort_certificates(CertList **data, WhichCerts ctype); #endif /* PITH_SMKEYS_INCLUDED */ |