~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to common/dns-cert.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dns-cert.c - DNS CERT code
 
2
 * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GNUPG.
 
5
 *
 
6
 * GNUPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 3 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GNUPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <sys/types.h>
 
22
#ifdef USE_DNS_CERT
 
23
# ifdef HAVE_W32_SYSTEM
 
24
# include <windows.h>
 
25
# else
 
26
# include <netinet/in.h>
 
27
# include <arpa/nameser.h>
 
28
# include <resolv.h>
 
29
# endif
 
30
#include <string.h>
 
31
#endif
 
32
 
 
33
#include "util.h"
 
34
#include "iobuf.h"
 
35
#include "dns-cert.h"
 
36
 
 
37
/* Not every installation has gotten around to supporting CERTs
 
38
   yet... */
 
39
#ifndef T_CERT
 
40
#define T_CERT 37
 
41
#endif
 
42
 
 
43
 
 
44
/* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for
 
45
   IPGP provided. */
 
46
int
 
47
get_dns_cert (const char *name,size_t max_size,IOBUF *iobuf,
 
48
              unsigned char **fpr,size_t *fpr_len,char **url)
 
49
{
 
50
#ifdef USE_DNS_CERT
 
51
  unsigned char *answer;
 
52
  int r,ret=-1;
 
53
  u16 count;
 
54
 
 
55
  if(fpr)
 
56
    *fpr=NULL;
 
57
 
 
58
  if(url)
 
59
    *url=NULL;
 
60
 
 
61
  answer=xmalloc(max_size);
 
62
 
 
63
  r=res_query(name,C_IN,T_CERT,answer,max_size);
 
64
  /* Not too big, not too small, no errors and at least 1 answer. */
 
65
  if(r>=sizeof(HEADER) && r<=max_size
 
66
     && (((HEADER *)answer)->rcode)==NOERROR
 
67
     && (count=ntohs(((HEADER *)answer)->ancount)))
 
68
    {
 
69
      int rc;
 
70
      unsigned char *pt,*emsg;
 
71
 
 
72
      emsg=&answer[r];
 
73
 
 
74
      pt=&answer[sizeof(HEADER)];
 
75
 
 
76
      /* Skip over the query */
 
77
 
 
78
      rc=dn_skipname(pt,emsg);
 
79
      if(rc==-1)
 
80
        goto fail;
 
81
 
 
82
      pt+=rc+QFIXEDSZ;
 
83
 
 
84
      /* There are several possible response types for a CERT request.
 
85
         We're interested in the PGP (a key) and IPGP (a URI) types.
 
86
         Skip all others.  TODO: A key is better than a URI since
 
87
         we've gone through all this bother to fetch it, so favor that
 
88
         if we have both PGP and IPGP? */
 
89
 
 
90
      while(count-->0 && pt<emsg)
 
91
        {
 
92
          u16 type,class,dlen,ctype;
 
93
 
 
94
          rc=dn_skipname(pt,emsg); /* the name we just queried for */
 
95
          if(rc==-1)
 
96
            break;
 
97
 
 
98
          pt+=rc;
 
99
 
 
100
          /* Truncated message? 15 bytes takes us to the point where
 
101
             we start looking at the ctype. */
 
102
          if((emsg-pt)<15)
 
103
            break;
 
104
 
 
105
          type=*pt++ << 8;
 
106
          type|=*pt++;
 
107
 
 
108
          class=*pt++ << 8;
 
109
          class|=*pt++;
 
110
          /* We asked for IN and got something else !? */
 
111
          if(class!=C_IN)
 
112
            break;
 
113
 
 
114
          /* ttl */
 
115
          pt+=4;
 
116
 
 
117
          /* data length */
 
118
          dlen=*pt++ << 8;
 
119
          dlen|=*pt++;
 
120
 
 
121
          /* We asked for CERT and got something else - might be a
 
122
             CNAME, so loop around again. */
 
123
          if(type!=T_CERT)
 
124
            {
 
125
              pt+=dlen;
 
126
              continue;
 
127
            }
 
128
 
 
129
          /* The CERT type */
 
130
          ctype=*pt++ << 8;
 
131
          ctype|=*pt++;
 
132
 
 
133
          /* Skip the CERT key tag and algo which we don't need. */
 
134
          pt+=3;
 
135
 
 
136
          dlen-=5;
 
137
 
 
138
          /* 15 bytes takes us to here */
 
139
 
 
140
          if(ctype==3 && iobuf && dlen)
 
141
            {
 
142
              /* PGP type */
 
143
              *iobuf=iobuf_temp_with_content((char *)pt,dlen);
 
144
              ret=1;
 
145
              break;
 
146
            }
 
147
          else if(ctype==6 && dlen && dlen<1023 && dlen>=pt[0]+1
 
148
                  && fpr && fpr_len && url)
 
149
            {
 
150
              /* IPGP type */
 
151
              *fpr_len=pt[0];
 
152
 
 
153
              if(*fpr_len)
 
154
                {
 
155
                  *fpr=xmalloc(*fpr_len);
 
156
                  memcpy(*fpr,&pt[1],*fpr_len);
 
157
                }
 
158
              else
 
159
                *fpr=NULL;
 
160
 
 
161
              if(dlen>*fpr_len+1)
 
162
                {
 
163
                  *url=xmalloc(dlen-(*fpr_len+1)+1);
 
164
                  memcpy(*url,&pt[*fpr_len+1],dlen-(*fpr_len+1));
 
165
                  (*url)[dlen-(*fpr_len+1)]='\0';
 
166
                }
 
167
              else
 
168
                *url=NULL;
 
169
 
 
170
              ret=2;
 
171
              break;
 
172
            }
 
173
 
 
174
          /* Neither type matches, so go around to the next answer. */
 
175
          pt+=dlen;
 
176
        }
 
177
    }
 
178
 
 
179
 fail:
 
180
  xfree(answer);
 
181
 
 
182
  return ret;
 
183
#else /* !USE_DNS_CERT */
 
184
  return -1;
 
185
#endif
 
186
}
 
187
 
 
188
 
 
189
 
 
190
/* Test with simon.josefsson.org */
 
191
 
 
192
#ifdef TEST
 
193
int
 
194
main(int argc,char *argv[])
 
195
{
 
196
  unsigned char *fpr;
 
197
  size_t fpr_len;
 
198
  char *url;
 
199
  int rc;
 
200
  IOBUF iobuf;
 
201
 
 
202
  if(argc!=2)
 
203
    {
 
204
      printf("cert-test [name]\n");
 
205
      return 1;
 
206
    }
 
207
 
 
208
  printf("CERT lookup on %s\n",argv[1]);
 
209
 
 
210
  rc=get_dns_cert (argv[1],16384,&iobuf,&fpr,&fpr_len,&url);
 
211
  if(rc==-1)
 
212
    printf("error\n");
 
213
  else if(rc==0)
 
214
    printf("no answer\n");
 
215
  else if(rc==1)
 
216
    {
 
217
      printf("key found: %d bytes\n",(int)iobuf_get_temp_length(iobuf));
 
218
      iobuf_close(iobuf);
 
219
    }
 
220
  else if(rc==2)
 
221
    {
 
222
      if(fpr)
 
223
        {
 
224
          size_t i;
 
225
          printf("Fingerprint found (%d bytes): ",(int)fpr_len);
 
226
          for(i=0;i<fpr_len;i++)
 
227
            printf("%02X",fpr[i]);
 
228
          printf("\n");
 
229
        }
 
230
      else
 
231
        printf("No fingerprint found\n");
 
232
 
 
233
      if(url)
 
234
        printf("URL found: %s\n",url);
 
235
      else
 
236
        printf("No URL found\n");
 
237
 
 
238
      xfree(fpr);
 
239
      xfree(url);
 
240
    }
 
241
 
 
242
  return 0;
 
243
}
 
244
#endif /* TEST */