xref: /freebsd/crypto/krb5/src/kprop/kprop_util.c (revision 4b15965daa99044daf184221b7c283bf7f2d7e66)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* kprop/kprop_util.c */
3 /*
4  * Copyright (C) 2010 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 /* sockaddr2krbaddr() utility function used by kprop and kpropd */
28 
29 #include "k5-int.h"
30 #include "kprop.h"
31 
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 
35 /*
36  * Convert an IPv4 or IPv6 socket address to a newly allocated krb5_address.
37  * There is similar code elsewhere in the tree, so this should possibly become
38  * a libkrb5 API in the future.
39  */
40 krb5_error_code
41 sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa,
42                  krb5_address **dest)
43 {
44     krb5_address addr;
45 
46     addr.magic = KV5M_ADDRESS;
47     if (family == AF_INET) {
48         struct sockaddr_in *sa4 = sa2sin(sa);
49         addr.addrtype = ADDRTYPE_INET;
50         addr.length = sizeof(sa4->sin_addr);
51         addr.contents = (krb5_octet *) &sa4->sin_addr;
52     } else if (family == AF_INET6) {
53         struct sockaddr_in6 *sa6 = sa2sin6(sa);
54         if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
55             addr.addrtype = ADDRTYPE_INET;
56             addr.contents = (krb5_octet *) &sa6->sin6_addr + 12;
57             addr.length = 4;
58         } else {
59             addr.addrtype = ADDRTYPE_INET6;
60             addr.length = sizeof(sa6->sin6_addr);
61             addr.contents = (krb5_octet *) &sa6->sin6_addr;
62         }
63     } else
64         return KRB5_PROG_ATYPE_NOSUPP;
65 
66     return krb5_copy_addr(context, &addr, dest);
67 }
68 
69 /* Construct a host-based principal, similar to krb5_sname_to_principal() but
70  * with a specified realm. */
71 krb5_error_code
72 sn2princ_realm(krb5_context context, const char *hostname, const char *sname,
73                const char *realm, krb5_principal *princ_out)
74 {
75     krb5_error_code ret;
76     krb5_principal princ;
77 
78     *princ_out = NULL;
79     assert(sname != NULL && realm != NULL);
80 
81     ret = krb5_sname_to_principal(context, hostname, sname, KRB5_NT_SRV_HST,
82                                   &princ);
83     if (ret)
84         return ret;
85 
86     ret = krb5_set_principal_realm(context, princ, realm);
87     if (ret) {
88         krb5_free_principal(context, princ);
89         return ret;
90     }
91 
92     *princ_out = princ;
93     return 0;
94 }
95 
96 void
97 encode_database_size(uint64_t size, krb5_data *buf)
98 {
99     assert(buf->length >= 12);
100     if (size > 0 && size <= UINT32_MAX) {
101         /* Encode in 32 bits for backward compatibility. */
102         store_32_be(size, buf->data);
103         buf->length = 4;
104     } else {
105         /* Set the first 32 bits to 0 and encode in the following 64 bits. */
106         store_32_be(0, buf->data);
107         store_64_be(size, buf->data + 4);
108         buf->length = 12;
109     }
110 }
111 
112 krb5_error_code
113 decode_database_size(const krb5_data *buf, uint64_t *size_out)
114 {
115     uint64_t size;
116 
117     if (buf->length == 12) {
118         /* A 12-byte buffer must have the first four bytes zeroed. */
119         if (load_32_be(buf->data) != 0)
120             return KRB5KRB_ERR_GENERIC;
121 
122         /* The size is stored in the next 64 bits.  Values from 1..2^32-1 must
123          * be encoded in four bytes. */
124         size = load_64_be(buf->data + 4);
125         if (size > 0 && size <= UINT32_MAX)
126             return KRB5KRB_ERR_GENERIC;
127     } else if (buf->length == 4) {
128         size = load_32_be(buf->data);
129     } else {
130         /* Invalid buffer size. */
131         return KRB5KRB_ERR_GENERIC;
132     }
133 
134     *size_out = size;
135     return 0;
136 }
137