Header And Logo

PostgreSQL
| The world's most advanced open source database.

pgp-info.c

Go to the documentation of this file.
00001 /*
00002  * pgp-info.c
00003  *    Provide info about PGP data.
00004  *
00005  * Copyright (c) 2005 Marko Kreen
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * contrib/pgcrypto/pgp-info.c
00030  */
00031 #include "postgres.h"
00032 
00033 #include "px.h"
00034 #include "mbuf.h"
00035 #include "pgp.h"
00036 
00037 static int
00038 read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
00039 {
00040     int         res;
00041     PGP_PubKey *pk = NULL;
00042 
00043     res = _pgp_read_public_key(pkt, &pk);
00044     if (res < 0)
00045         goto err;
00046 
00047     /* skip secret key part, if it exists */
00048     res = pgp_skip_packet(pkt);
00049     if (res < 0)
00050         goto err;
00051 
00052     /* is it encryption key */
00053     switch (pk->algo)
00054     {
00055         case PGP_PUB_ELG_ENCRYPT:
00056         case PGP_PUB_RSA_ENCRYPT:
00057         case PGP_PUB_RSA_ENCRYPT_SIGN:
00058             memcpy(keyid_buf, pk->key_id, 8);
00059             res = 1;
00060             break;
00061         default:
00062             res = 0;
00063     }
00064 
00065 err:
00066     pgp_key_free(pk);
00067     return res;
00068 }
00069 
00070 static int
00071 read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf)
00072 {
00073     uint8       ver;
00074     int         res;
00075 
00076     GETBYTE(pkt, ver);
00077     if (ver != 3)
00078         return -1;
00079 
00080     res = pullf_read_fixed(pkt, 8, keyid_buf);
00081     if (res < 0)
00082         return res;
00083 
00084     return pgp_skip_packet(pkt);
00085 }
00086 
00087 static const char hextbl[] = "0123456789ABCDEF";
00088 
00089 static int
00090 print_key(uint8 *keyid, char *dst)
00091 {
00092     int         i;
00093     unsigned    c;
00094 
00095     for (i = 0; i < 8; i++)
00096     {
00097         c = keyid[i];
00098         *dst++ = hextbl[(c >> 4) & 0x0F];
00099         *dst++ = hextbl[c & 0x0F];
00100     }
00101     *dst = 0;
00102     return 8 * 2;
00103 }
00104 
00105 static const uint8 any_key[] =
00106 {0, 0, 0, 0, 0, 0, 0, 0};
00107 
00108 /*
00109  * dst should have room for 17 bytes
00110  */
00111 int
00112 pgp_get_keyid(MBuf *pgp_data, char *dst)
00113 {
00114     int         res;
00115     PullFilter *src;
00116     PullFilter *pkt = NULL;
00117     int         len;
00118     uint8       tag;
00119     int         got_pub_key = 0,
00120                 got_symenc_key = 0,
00121                 got_pubenc_key = 0;
00122     int         got_data = 0;
00123     uint8       keyid_buf[8];
00124     int         got_main_key = 0;
00125 
00126 
00127     res = pullf_create_mbuf_reader(&src, pgp_data);
00128     if (res < 0)
00129         return res;
00130 
00131     while (1)
00132     {
00133         res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
00134         if (res <= 0)
00135             break;
00136         res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
00137         if (res < 0)
00138             break;
00139 
00140         switch (tag)
00141         {
00142             case PGP_PKT_SECRET_KEY:
00143             case PGP_PKT_PUBLIC_KEY:
00144                 /* main key is for signing, so ignore it */
00145                 if (!got_main_key)
00146                 {
00147                     got_main_key = 1;
00148                     res = pgp_skip_packet(pkt);
00149                 }
00150                 else
00151                     res = PXE_PGP_MULTIPLE_KEYS;
00152                 break;
00153             case PGP_PKT_SECRET_SUBKEY:
00154             case PGP_PKT_PUBLIC_SUBKEY:
00155                 res = read_pubkey_keyid(pkt, keyid_buf);
00156                 if (res < 0)
00157                     break;
00158                 if (res > 0)
00159                     got_pub_key++;
00160                 break;
00161             case PGP_PKT_PUBENCRYPTED_SESSKEY:
00162                 got_pubenc_key++;
00163                 res = read_pubenc_keyid(pkt, keyid_buf);
00164                 break;
00165             case PGP_PKT_SYMENCRYPTED_DATA:
00166             case PGP_PKT_SYMENCRYPTED_DATA_MDC:
00167                 /* don't skip it, just stop */
00168                 got_data = 1;
00169                 break;
00170             case PGP_PKT_SYMENCRYPTED_SESSKEY:
00171                 got_symenc_key++;
00172                 /* fallthru */
00173             case PGP_PKT_SIGNATURE:
00174             case PGP_PKT_MARKER:
00175             case PGP_PKT_TRUST:
00176             case PGP_PKT_USER_ID:
00177             case PGP_PKT_USER_ATTR:
00178             case PGP_PKT_PRIV_61:
00179                 res = pgp_skip_packet(pkt);
00180                 break;
00181             default:
00182                 res = PXE_PGP_CORRUPT_DATA;
00183         }
00184 
00185         if (pkt)
00186             pullf_free(pkt);
00187         pkt = NULL;
00188 
00189         if (res < 0 || got_data)
00190             break;
00191     }
00192 
00193     pullf_free(src);
00194     if (pkt)
00195         pullf_free(pkt);
00196 
00197     if (res < 0)
00198         return res;
00199 
00200     /* now check sanity */
00201     if (got_pub_key && got_pubenc_key)
00202         res = PXE_PGP_CORRUPT_DATA;
00203 
00204     if (got_pub_key > 1)
00205         res = PXE_PGP_MULTIPLE_KEYS;
00206 
00207     if (got_pubenc_key > 1)
00208         res = PXE_PGP_MULTIPLE_KEYS;
00209 
00210     /*
00211      * if still ok, look what we got
00212      */
00213     if (res >= 0)
00214     {
00215         if (got_pubenc_key || got_pub_key)
00216         {
00217             if (memcmp(keyid_buf, any_key, 8) == 0)
00218             {
00219                 memcpy(dst, "ANYKEY", 7);
00220                 res = 6;
00221             }
00222             else
00223                 res = print_key(keyid_buf, dst);
00224         }
00225         else if (got_symenc_key)
00226         {
00227             memcpy(dst, "SYMKEY", 7);
00228             res = 6;
00229         }
00230         else
00231             res = PXE_PGP_NO_USABLE_KEY;
00232     }
00233 
00234     return res;
00235 }