7 Kerberos Change Password Protocol (I-D) variant for Windows 2000
13 #include "asn1_make.h"
21 #include <sys/socket.h>
24 #include <arpa/nameser.h>
29 #ifdef HAVE_NETINET_IN_H
30 #define KRB5_USE_INET 1
39 typedef krb5_octet asn1_octet;
40 typedef krb5_error_code asn1_error_code;
41 typedef struct code_buffer_rep {
42 char *base, *bound, *next;
44 typedef enum { UNIVERSAL = 0x00, APPLICATION = 0x40,
45 CONTEXT_SPECIFIC = 0x80, PRIVATE = 0xC0 } asn1_class;
48 static const char rcsid[] = "$Id$";
50 asn1_error_code asn1_encode_realm(asn1buf *buf, const krb5_principal val,
52 asn1_error_code asn1_encode_principal_name(asn1buf *buf,
53 const krb5_principal val,
55 asn1_error_code asn1_encode_octetstring(asn1buf *buf, const int len,
56 const asn1_octet *val, int *retlen);
58 /* From src/lib/krb5/asn.1/krb5_encode.c */
60 /* setup() -- create and initialize bookkeeping variables
61 retval: stores error codes returned from subroutines
62 buf: the coding buffer
63 length: length of the most-recently produced encoding
64 sum: cumulative length of the entire encoding */
66 asn1_error_code retval;\
70 if(rep == NULL) return ASN1_MISSING_FIELD;\
72 retval = asn1buf_create(&buf);\
73 if(retval) return retval
76 /* krb5_addfield -- add a field, or component, to the encoding */
77 #define krb5_addfield(value,tag,encoder)\
78 { retval = encoder(buf,value,&length);\
80 asn1buf_destroy(&buf);\
83 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
85 asn1buf_destroy(&buf);\
89 /* krb5_addlenfield -- add a field whose length must be separately specified */
90 #define krb5_addlenfield(len,value,tag,encoder)\
91 { retval = encoder(buf,len,value,&length);\
93 asn1buf_destroy(&buf);\
96 retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,tag,length,&length);\
98 asn1buf_destroy(&buf);\
102 /* form a sequence (by adding a sequence header to the current encoding) */
103 #define krb5_makeseq()\
104 retval = asn1_make_sequence(buf,sum,&length);\
106 asn1buf_destroy(&buf);\
110 /* produce the final output and clean up the workspace */
111 #define krb5_cleanup()\
112 retval = asn12krb5_buf(buf,code);\
114 asn1buf_destroy(&buf);\
116 retval = asn1buf_destroy(&buf);\
122 krb5_error_code encode_krb5_setpw(const krb5_setpw *rep,
127 if (rep->targprinc != NULL)
128 { /* target principal name is OPTIONAL */
129 krb5_addfield(rep->targprinc,2,asn1_encode_realm);
130 krb5_addfield(rep->targprinc,1,asn1_encode_principal_name);
132 krb5_addlenfield(rep->newpasswd.length, rep->newpasswd.data,
133 0, asn1_encode_octetstring);
139 krb5_locate_dns_srv(krb5_context context, const krb5_data *realm,
140 const char *service, const char *protocol,
141 struct sockaddr **addr_pp, int *naddrs)
147 unsigned char reply[1024];
155 struct sockaddr *addr_p = NULL;
156 struct sockaddr_in *sin_p;
159 addr_p = (struct sockaddr *)malloc (sizeof (struct sockaddr));
165 snprintf(host, sizeof(host), "%s.%s.%*s.",
166 service, protocol, realm->length, realm->data);
168 sprintf(host, "%s.%s.%*s.",
169 service, protocol, realm->length, realm->data);
171 len = res_search(host, C_IN, T_SRV, reply, sizeof(reply));
176 status = dn_expand(reply, reply + len, p, host, sizeof(host));
181 while (p < reply + len)
183 int type, class, ttl, size;
184 status = dn_expand(reply, reply + len, p, host, sizeof(host));
188 type = (p[0] << 8) | p[1];
190 class = (p[0] << 8) | p[1];
192 ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
194 size = (p[0] << 8) | p[1];
198 status = dn_expand(reply, reply + len, p + 6, host, sizeof(host));
201 priority = (p[0] << 8) | p[1];
202 weight = (p[2] << 8) | p[3];
203 port = (p[4] << 8) | p[5];
204 hp = (struct hostent *)gethostbyname(host);
207 switch (hp->h_addrtype)
211 for (j=0; hp->h_addr_list[j]; j++)
213 sin_p = (struct sockaddr_in *) &addr_p[out++];
214 memset ((char *)sin_p, 0, sizeof(struct sockaddr));
215 sin_p->sin_family = hp->h_addrtype;
216 sin_p->sin_port = htons(port);
217 memcpy((char *)&sin_p->sin_addr,
218 (char *)hp->h_addr_list[j],
219 sizeof(struct in_addr));
223 addr_p = (struct sockaddr *)
224 realloc ((char *)addr_p,
225 sizeof(struct sockaddr) * count);
245 return(KRB5_REALM_CANT_RESOLVE);
254 krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
255 struct sockaddr **addr_pp, int *naddrs)
257 krb5_error_code code;
258 code = krb5_locate_dns_srv(context, realm, "_kpasswd", "_udp",
261 code = krb5_locate_dns_srv(context, realm, "_kpasswd", "_tcp",