155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 2001 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
3555682Smarkm
3655682Smarkm/*
3755682Smarkm * Try to find out what's a reasonable default principal.
3855682Smarkm */
3955682Smarkm
4078527Sassarstatic const char*
4178527Sassarget_env_user(void)
4278527Sassar{
4378527Sassar    const char *user = getenv("USER");
4478527Sassar    if(user == NULL)
4578527Sassar	user = getenv("LOGNAME");
4678527Sassar    if(user == NULL)
4778527Sassar	user = getenv("USERNAME");
4878527Sassar    return user;
4978527Sassar}
5078527Sassar
51233294Sstas#ifndef _WIN32
52233294Sstas
53178825Sdfr/*
54178825Sdfr * Will only use operating-system dependant operation to get the
55178825Sdfr * default principal, for use of functions that in ccache layer to
56178825Sdfr * avoid recursive calls.
57178825Sdfr */
58178825Sdfr
5955682Smarkmkrb5_error_code
60233294Sstas_krb5_get_default_principal_local (krb5_context context,
61178825Sdfr				   krb5_principal *princ)
6255682Smarkm{
6355682Smarkm    krb5_error_code ret;
6455682Smarkm    const char *user;
6578527Sassar    uid_t uid;
6655682Smarkm
67178825Sdfr    *princ = NULL;
6855682Smarkm
69233294Sstas    uid = getuid();
7078527Sassar    if(uid == 0) {
7178527Sassar	user = getlogin();
7278527Sassar	if(user == NULL)
7378527Sassar	    user = get_env_user();
7478527Sassar	if(user != NULL && strcmp(user, "root") != 0)
7578527Sassar	    ret = krb5_make_principal(context, princ, NULL, user, "root", NULL);
7678527Sassar	else
7778527Sassar	    ret = krb5_make_principal(context, princ, NULL, "root", NULL);
7855682Smarkm    } else {
79233294Sstas	struct passwd *pw = getpwuid(uid);
8078527Sassar	if(pw != NULL)
8178527Sassar	    user = pw->pw_name;
8278527Sassar	else {
8378527Sassar	    user = get_env_user();
8478527Sassar	    if(user == NULL)
8578527Sassar		user = getlogin();
8678527Sassar	}
8778527Sassar	if(user == NULL) {
88233294Sstas	    krb5_set_error_message(context, ENOTTY,
89233294Sstas				   N_("unable to figure out current "
90233294Sstas				      "principal", ""));
9178527Sassar	    return ENOTTY; /* XXX */
9278527Sassar	}
9355682Smarkm	ret = krb5_make_principal(context, princ, NULL, user, NULL);
9455682Smarkm    }
9555682Smarkm    return ret;
9655682Smarkm}
97178825Sdfr
98233294Sstas#else  /* _WIN32 */
99233294Sstas
100233294Sstas#define SECURITY_WIN32
101233294Sstas#include <security.h>
102233294Sstas
103233294Sstaskrb5_error_code
104233294Sstas_krb5_get_default_principal_local(krb5_context context,
105233294Sstas				  krb5_principal *princ)
106233294Sstas{
107233294Sstas    /* See if we can get the principal first.  We only expect this to
108233294Sstas       work if logged into a domain. */
109233294Sstas    {
110233294Sstas	char username[1024];
111233294Sstas	ULONG sz = sizeof(username);
112233294Sstas
113233294Sstas	if (GetUserNameEx(NameUserPrincipal, username, &sz)) {
114233294Sstas	    return krb5_parse_name_flags(context, username,
115233294Sstas					 KRB5_PRINCIPAL_PARSE_ENTERPRISE,
116233294Sstas					 princ);
117233294Sstas	}
118233294Sstas    }
119233294Sstas
120233294Sstas    /* Just get the Windows username.  This should pretty much always
121233294Sstas       work. */
122233294Sstas    {
123233294Sstas	char username[1024];
124233294Sstas	DWORD dsz = sizeof(username);
125233294Sstas
126233294Sstas	if (GetUserName(username, &dsz)) {
127233294Sstas	    return krb5_make_principal(context, princ, NULL, username, NULL);
128233294Sstas	}
129233294Sstas    }
130233294Sstas
131233294Sstas    /* Failing that, we look at the environment */
132233294Sstas    {
133233294Sstas	const char * username = get_env_user();
134233294Sstas
135233294Sstas	if (username == NULL) {
136233294Sstas	    krb5_set_error_string(context,
137233294Sstas				  "unable to figure out current principal");
138233294Sstas	    return ENOTTY;	/* Really? */
139233294Sstas	}
140233294Sstas
141233294Sstas	return krb5_make_principal(context, princ, NULL, username, NULL);
142233294Sstas    }
143233294Sstas}
144233294Sstas
145233294Sstas#endif
146233294Sstas
147233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
148178825Sdfrkrb5_get_default_principal (krb5_context context,
149178825Sdfr			    krb5_principal *princ)
150178825Sdfr{
151178825Sdfr    krb5_error_code ret;
152178825Sdfr    krb5_ccache id;
153178825Sdfr
154178825Sdfr    *princ = NULL;
155178825Sdfr
156178825Sdfr    ret = krb5_cc_default (context, &id);
157178825Sdfr    if (ret == 0) {
158178825Sdfr	ret = krb5_cc_get_principal (context, id, princ);
159178825Sdfr	krb5_cc_close (context, id);
160178825Sdfr	if (ret == 0)
161178825Sdfr	    return 0;
162178825Sdfr    }
163178825Sdfr
164178825Sdfr    return _krb5_get_default_principal_local(context, princ);
165178825Sdfr}
166