xref: /onnv-gate/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c (revision 12508:edb7861a1533)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
2111411SSurya.Prakki@Sun.COM 
225331Samw /*
23*12508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw  */
255331Samw /*
265331Samw  * Copyright 1990 by the Massachusetts Institute of Technology.
275331Samw  * All Rights Reserved.
285331Samw  *
295331Samw  * Export of this software from the United States of America may
305331Samw  *   require a specific license from the United States Government.
315331Samw  *   It is the responsibility of any person or organization contemplating
325331Samw  *   export to obtain such a license before exporting.
335331Samw  *
345331Samw  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
355331Samw  * distribute this software and its documentation for any purpose and
365331Samw  * without fee is hereby granted, provided that the above copyright
375331Samw  * notice appear in all copies and that both that copyright notice and
385331Samw  * this permission notice appear in supporting documentation, and that
395331Samw  * the name of M.I.T. not be used in advertising or publicity pertaining
405331Samw  * to distribution of the software without specific, written prior
415331Samw  * permission.  Furthermore if you modify this software you must label
425331Samw  * your software as modified software and not distribute it in such a
435331Samw  * fashion that it might be confused with the original M.I.T. software.
445331Samw  * M.I.T. makes no representations about the suitability of
455331Samw  * this software for any purpose.  It is provided "as is" without express
465331Samw  * or implied warranty.
475331Samw  *
485331Samw  *
495331Samw  * Initialize a credentials cache.
505331Samw  */
515331Samw #include <kerberosv5/krb5.h>
525331Samw #include <kerberosv5/com_err.h>
535521Sas200622 #include <assert.h>
545331Samw #include <stdio.h>
555331Samw #include <syslog.h>
566139Sjb150015 #include <errno.h>
575331Samw 
585331Samw #include <smbsrv/libsmbns.h>
595331Samw #include <smbns_krb.h>
605331Samw 
6110717Samw@Sun.COM int
smb_kinit(char * principal_name,char * principal_passwd)6210717Samw@Sun.COM smb_kinit(char *principal_name, char *principal_passwd)
635331Samw {
6410717Samw@Sun.COM 	krb5_context ctx = NULL;
6510717Samw@Sun.COM 	krb5_ccache cc = NULL;
6610717Samw@Sun.COM 	krb5_principal me = NULL;
6710717Samw@Sun.COM 	krb5_creds my_creds;
6810717Samw@Sun.COM 	krb5_error_code code;
6910717Samw@Sun.COM 	const char *errmsg = NULL;
7010717Samw@Sun.COM 	const char *doing = NULL;
715331Samw 
7210717Samw@Sun.COM 	assert(principal_name != NULL);
7310717Samw@Sun.COM 	assert(principal_passwd != NULL);
745331Samw 
755331Samw 	(void) memset(&my_creds, 0, sizeof (my_creds));
765331Samw 
775331Samw 	/*
7810717Samw@Sun.COM 	 * From this point on, we can goto cleanup because the key variables
7910717Samw@Sun.COM 	 * are initialized.
805331Samw 	 */
815331Samw 
8210717Samw@Sun.COM 	code = krb5_init_context(&ctx);
835331Samw 	if (code) {
84*12508Samw@Sun.COM 		doing = "smbns_krb: initializing context";
855331Samw 		goto cleanup;
865331Samw 	}
875331Samw 
8810717Samw@Sun.COM 	code = krb5_cc_default(ctx, &cc);
8910717Samw@Sun.COM 	if (code != 0) {
90*12508Samw@Sun.COM 		doing = "smbns_krb: resolve default credentials cache";
915331Samw 		goto cleanup;
925331Samw 	}
935331Samw 
9410717Samw@Sun.COM 	/* Use specified name */
9510717Samw@Sun.COM 	code = krb5_parse_name(ctx, principal_name, &me);
9610717Samw@Sun.COM 	if (code != 0) {
97*12508Samw@Sun.COM 		doing = "smbns_krb: parsing principal name";
985331Samw 		goto cleanup;
995331Samw 	}
1005331Samw 
10110717Samw@Sun.COM 	code = krb5_get_init_creds_password(ctx, &my_creds, me,
10210717Samw@Sun.COM 	    principal_passwd, NULL, 0, (krb5_deltat)0,
10310717Samw@Sun.COM 	    NULL, NULL);
10410717Samw@Sun.COM 	if (code != 0) {
105*12508Samw@Sun.COM 		doing = "smbns_krb: getting initial credentials";
1065331Samw 
10710717Samw@Sun.COM 		if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
108*12508Samw@Sun.COM 			errmsg = "smbns_krb: Password incorrect";
10910717Samw@Sun.COM 		}
1105521Sas200622 
11110717Samw@Sun.COM 		goto cleanup;
11210717Samw@Sun.COM 	}
1135331Samw 
11410717Samw@Sun.COM 	code = krb5_cc_initialize(ctx, cc, me);
11510717Samw@Sun.COM 	if (code != 0) {
116*12508Samw@Sun.COM 		doing = "smbns_krb: initializing cache";
11710717Samw@Sun.COM 		goto cleanup;
1185331Samw 	}
1195331Samw 
12010717Samw@Sun.COM 	code = krb5_cc_store_cred(ctx, cc, &my_creds);
12110717Samw@Sun.COM 	if (code != 0) {
122*12508Samw@Sun.COM 		doing = "smbns_krb: storing credentials";
12310717Samw@Sun.COM 		goto cleanup;
1245331Samw 	}
1255331Samw 
12610717Samw@Sun.COM 	/* SUCCESS! */
1275331Samw 
12810717Samw@Sun.COM cleanup:
12910717Samw@Sun.COM 	if (code != 0) {
13010717Samw@Sun.COM 		if (errmsg == NULL)
131*12508Samw@Sun.COM 			smb_krb5_log_errmsg(ctx, doing, code);
132*12508Samw@Sun.COM 		else
133*12508Samw@Sun.COM 			syslog(LOG_ERR, "%s (%s)", doing, errmsg);
1345331Samw 	}
1355521Sas200622 
13610717Samw@Sun.COM 	if (my_creds.client == me) {
13710717Samw@Sun.COM 		my_creds.client = NULL;
13810717Samw@Sun.COM 	}
13910717Samw@Sun.COM 	krb5_free_cred_contents(ctx, &my_creds);
1405331Samw 
14110717Samw@Sun.COM 	if (me)
14210717Samw@Sun.COM 		krb5_free_principal(ctx, me);
14310717Samw@Sun.COM 	if (cc)
14411411SSurya.Prakki@Sun.COM 		(void) krb5_cc_close(ctx, cc);
14510717Samw@Sun.COM 	if (ctx)
14610717Samw@Sun.COM 		krb5_free_context(ctx);
1475331Samw 
14810717Samw@Sun.COM 	return (code == 0);
1495331Samw }
1506139Sjb150015 
1516139Sjb150015 /*
152*12508Samw@Sun.COM  * Invoke krb5_get_error_message() to generate a richer error message.
153*12508Samw@Sun.COM  */
154*12508Samw@Sun.COM void
smb_krb5_log_errmsg(krb5_context ctx,const char * prefix,krb5_error_code code)155*12508Samw@Sun.COM smb_krb5_log_errmsg(krb5_context ctx, const char *prefix, krb5_error_code code)
156*12508Samw@Sun.COM {
157*12508Samw@Sun.COM 	const char *msg;
158*12508Samw@Sun.COM 
159*12508Samw@Sun.COM 	msg = krb5_get_error_message(ctx, code);
160*12508Samw@Sun.COM 	syslog(LOG_ERR, "%s (%s)", prefix, msg);
161*12508Samw@Sun.COM 	krb5_free_error_message(ctx, msg);
162*12508Samw@Sun.COM }
163*12508Samw@Sun.COM 
164*12508Samw@Sun.COM /*
1656139Sjb150015  * smb_ccache_init
1666139Sjb150015  *
1676139Sjb150015  * Creates the directory where the Kerberos ccache file is located
1686139Sjb150015  * and set KRB5CCNAME in the environment.
1696139Sjb150015  *
1706139Sjb150015  * Returns 0 upon succcess.  Otherwise, returns
1716139Sjb150015  * -1 if it fails to create the specified directory fails.
1726139Sjb150015  * -2 if it fails to set the KRB5CCNAME environment variable.
1736139Sjb150015  */
1746139Sjb150015 int
smb_ccache_init(char * dir,char * filename)1756139Sjb150015 smb_ccache_init(char *dir, char *filename)
1766139Sjb150015 {
1776139Sjb150015 	static char buf[MAXPATHLEN];
1786139Sjb150015 
1796139Sjb150015 	if ((mkdir(dir, 0700) < 0) && (errno != EEXIST))
1806139Sjb150015 		return (-1);
1816139Sjb150015 
1826139Sjb150015 	(void) snprintf(buf, MAXPATHLEN, "KRB5CCNAME=%s/%s", dir, filename);
1836139Sjb150015 	if (putenv(buf) != 0)
1846139Sjb150015 		return (-2);
1856139Sjb150015 	return (0);
1866139Sjb150015 }
1876139Sjb150015 
1886139Sjb150015 void
smb_ccache_remove(char * path)1896139Sjb150015 smb_ccache_remove(char *path)
1906139Sjb150015 {
1916139Sjb150015 	if ((remove(path) < 0) && (errno != ENOENT))
192*12508Samw@Sun.COM 		syslog(LOG_ERR, "smbns_krb: failed to remove ccache (%s)",
193*12508Samw@Sun.COM 		    path);
1946139Sjb150015 }
195