1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/krad/t_packet.c - RADIUS packet test program */ 3 /* 4 * Copyright 2013 Red Hat, Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "t_daemon.h" 31 32 #define ACCEPT_PACKET 0 33 #define REJECT_PACKET 1 34 35 static krad_packet *packets[3]; 36 37 static const krad_packet * 38 iterator(void *data, krb5_boolean cancel) 39 { 40 krad_packet *tmp; 41 int *i = data; 42 43 if (cancel || packets[*i] == NULL) 44 return NULL; 45 46 tmp = packets[*i]; 47 *i += 1; 48 return tmp; 49 } 50 51 static krb5_error_code 52 make_packet(krb5_context ctx, const krb5_data *username, 53 const krb5_data *password, krad_packet **pkt) 54 { 55 krad_attrset *set = NULL; 56 krad_packet *tmp = NULL; 57 krb5_error_code retval; 58 const krb5_data *data; 59 int i = 0; 60 krb5_data nas_id; 61 62 nas_id = string2data("12345678901234567890123456789012345678901234567890" 63 "12345678901234567890123456789012345678901234567890" 64 "12345678901234567890123456789012345678901234567890" 65 "12345678901234567890123456789012345678901234567890" 66 "12345678901234567890123456789012345678901234567890" 67 "123"); 68 69 retval = krad_attrset_new(ctx, &set); 70 if (retval != 0) 71 goto out; 72 73 retval = krad_attrset_add(set, KRAD_ATTR_USER_NAME, username); 74 if (retval != 0) 75 goto out; 76 77 retval = krad_attrset_add(set, KRAD_ATTR_USER_PASSWORD, 78 password); 79 if (retval != 0) 80 goto out; 81 82 retval = krad_attrset_add(set, KRAD_ATTR_NAS_IDENTIFIER, &nas_id); 83 if (retval != 0) 84 goto out; 85 86 retval = krad_packet_new_request(ctx, "foo", KRAD_CODE_ACCESS_REQUEST, 87 set, iterator, &i, &tmp); 88 if (retval != 0) 89 goto out; 90 91 data = krad_packet_get_attr(tmp, KRAD_ATTR_USER_NAME, 0); 92 if (data == NULL) { 93 retval = ENOENT; 94 goto out; 95 } 96 97 if (data->length != username->length || 98 memcmp(data->data, username->data, data->length) != 0) { 99 retval = EINVAL; 100 goto out; 101 } 102 103 *pkt = tmp; 104 tmp = NULL; 105 106 out: 107 krad_attrset_free(set); 108 krad_packet_free(tmp); 109 return retval; 110 } 111 112 static krb5_error_code 113 do_auth(krb5_context ctx, struct addrinfo *ai, const char *secret, 114 const krad_packet *rqst, krb5_boolean *auth) 115 { 116 const krad_packet *req = NULL; 117 char tmp[KRAD_PACKET_SIZE_MAX]; 118 const krb5_data *request; 119 krad_packet *rsp = NULL; 120 krb5_error_code retval; 121 krb5_data response; 122 int sock = -1, i; 123 124 response = make_data(tmp, sizeof(tmp)); 125 126 sock = socket(ai->ai_family, ai->ai_socktype, 0); 127 if (sock < 0) { 128 retval = errno; 129 goto out; 130 } 131 132 request = krad_packet_encode(rqst); 133 if (sendto(sock, request->data, request->length, 0, ai->ai_addr, 134 ai->ai_addrlen) < 0) { 135 retval = errno; 136 goto out; 137 } 138 139 i = recv(sock, response.data, sizeof(tmp), 0); 140 if (i < 0) { 141 retval = errno; 142 goto out; 143 } 144 response.length = i; 145 146 i = 0; 147 retval = krad_packet_decode_response(ctx, secret, &response, iterator, &i, 148 &req, &rsp); 149 if (retval != 0) 150 goto out; 151 152 if (req != rqst) { 153 retval = EBADMSG; 154 goto out; 155 } 156 157 *auth = krad_packet_get_code(rsp) == KRAD_CODE_ACCESS_ACCEPT; 158 159 out: 160 krad_packet_free(rsp); 161 if (sock >= 0) 162 close(sock); 163 return retval; 164 } 165 166 int 167 main(int argc, const char **argv) 168 { 169 struct addrinfo *ai = NULL, hints; 170 krb5_data username, password; 171 krb5_boolean auth = FALSE; 172 krb5_context ctx; 173 const krad_packet *dupreq; 174 const krb5_data *encpkt; 175 krad_packet *decreq; 176 177 username = string2data("testUser"); 178 179 if (!daemon_start(argc, argv)) { 180 fprintf(stderr, "Unable to start pyrad daemon, skipping test...\n"); 181 return 0; 182 } 183 184 noerror(krb5_init_context(&ctx)); 185 186 password = string2data("accept"); 187 noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET])); 188 encpkt = krad_packet_encode(packets[ACCEPT_PACKET]); 189 noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL, 190 &dupreq, &decreq)); 191 krad_packet_free(decreq); 192 193 password = string2data("reject"); 194 noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET])); 195 encpkt = krad_packet_encode(packets[REJECT_PACKET]); 196 noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL, 197 &dupreq, &decreq)); 198 krad_packet_free(decreq); 199 200 memset(&hints, 0, sizeof(hints)); 201 hints.ai_family = AF_INET; 202 hints.ai_socktype = SOCK_DGRAM; 203 noerror(gai_error_code(getaddrinfo("127.0.0.1", "radius", &hints, &ai))); 204 205 noerror(do_auth(ctx, ai, "foo", packets[ACCEPT_PACKET], &auth)); 206 insist(auth == TRUE); 207 208 noerror(do_auth(ctx, ai, "foo", packets[REJECT_PACKET], &auth)); 209 insist(auth == FALSE); 210 211 krad_packet_free(packets[ACCEPT_PACKET]); 212 krad_packet_free(packets[REJECT_PACKET]); 213 krb5_free_context(ctx); 214 freeaddrinfo(ai); 215 return 0; 216 } 217