changepw.c revision 505d05c73a6e56769f263d4803b22eddd168ee24
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/changepw.c
*
* Copyright 1990,1999 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*/
#define NEED_SOCKETS
#include <krb5.h>
#include <k5-int.h>
#include <client_internal.h>
#include <gssapi_krb5.h>
#include <gssapiP_krb5.h>
/* #include "adm_err.h" */
#include <stdio.h>
#include <errno.h>
/*
* _kadm5_get_kpasswd_protocol
*
* returns the password change protocol value to the caller.
* Since the 'handle' is an opaque value to higher up callers,
* this method is needed to provide a way for them to get a peek
* at the protocol being used without having to expose the entire
* handle structure.
*/
{
}
/*
* krb5_change_password
*
* Prepare and send a CHANGEPW request to a password server
* using UDP datagrams. This is only used for sending to
* non-SEAM servers which support the Marc Horowitz defined
* protocol (1998) for password changing.
*
* SUNW14resync - added _local as it conflicts with one in krb5.h
*/
static krb5_error_code
char *newpw;
{
krb5_error_code code = 0;
int i, addrlen;
struct sockaddr_in *sin_p;
int naddr_p;
/* Initialize values so that cleanup call can safely check for NULL */
auth_context = NULL;
/* initialize auth_context so that we know we have to free it */
goto cleanup;
goto cleanup;
/*
* find the address of the kpasswd_server.
*/
if (!addr_p)
goto cleanup;
goto cleanup;
}
naddr_p = 1;
/*
* this is really obscure. s1 is used for all communications. it
* is left unconnected in case the server is multihomed and routes
* are asymmetric. s2 is connected to resolve routes and get
* addresses. this is the *only* way to get proper addresses for
* multihomed hosts if routing is asymmetric.
*
* A related problem in the server, but not the client, is that
* many os's have no way to disconnect a connected udp socket, so
* the s2 socket needs to be closed and recreated for each
* request. The s1 socket must not be closed, or else queued
* requests will be lost.
*
* A "naive" client implementation (one socket, no connect,
* hostname resolution to get the local ip addr) will work and
* interoperate if the client is single-homed.
*/
{
goto cleanup;
}
{
goto cleanup;
}
for (i = 0; i < naddr_p; i++)
{
{
if ((errno == ECONNREFUSED) ||
(errno == EHOSTUNREACH))
continue; /* try the next addr */
goto cleanup;
}
addrlen = sizeof (local_addr);
{
if ((errno == ECONNREFUSED) ||
(errno == EHOSTUNREACH))
continue; /* try the next addr */
goto cleanup;
}
/*
* some brain-dead OS's don't return useful information from
* the getsockname call. Namely, windows and solaris.
*/
{
&local_addr)->sin_addr);
&(((struct sockaddr_in *)
&local_addr)->sin_addr);
}
else
{
}
addrlen = sizeof (remote_addr);
{
if ((errno == ECONNREFUSED) ||
(errno == EHOSTUNREACH))
continue; /* try the next addr */
goto cleanup;
}
&remote_addr)->sin_addr);
/*
* mk_priv requires that the local address be set.
* getsockname is used for this. rd_priv requires that the
* remote address be set. recvfrom is used for this. If
* rd_priv is given a local address, and the message has the
* recipient addr in it, this will be checked. However, there
* is simply no way to know ahead of time what address the
* message will be delivered *to*. Therefore, it is important
* that either no recipient address is in the messages when
* mk_priv is called, or that no local address is passed to
* rd_priv. Both is a better idea, and I have done that. In
* summary, when mk_priv is called, *only* a local address is
* specified. when rd_priv is called, *only* a remote address
* is specified. Are we having fun yet?
*/
&local_kaddr, NULL))
{
goto cleanup;
}
{
goto cleanup;
}
{
(errno == EHOSTUNREACH)))
continue; /* try the next addr */
goto cleanup;
}
case -1:
goto cleanup;
case 0:
goto cleanup;
default:
/* fall through */
;
}
{
goto cleanup;
}
s1 = INVALID_SOCKET;
s2 = INVALID_SOCKET;
NULL, &remote_kaddr))
goto cleanup;
goto cleanup;
if (srvr_rsp_code)
code = 0;
goto cleanup;
}
if (auth_context != NULL)
if (s1 != INVALID_SOCKET)
if (s2 != INVALID_SOCKET)
return (code);
}
/*
* kadm5_chpass_principal_v2
*
* New function used to prepare to make the change password request to a
* non-SEAM admin server. The protocol used in this case is not based on
* RPCSEC_GSS, it simply makes the request to port 464 (udp and tcp).
* This is the same way that MIT KRB5 1.2.1 changes passwords.
*/
char *newpw,
{
int cpwlen;
char *cpw_service = NULL;
/*
* The credentials have already been stored in the cache in the
* initialization step earlier, but we dont have direct access to it
* at this level. Derive the cache and fetch the credentials to use for
* sending the request.
*/
&ccache)))
return (code);
/* set the client principal in the credential match structure */
/*
* match struct
*/
if (cpw_service == NULL) {
return (ENOMEM);
}
/* generate the server principal from the name string we generated */
return (code);
}
/* Find the credentials in the cache */
&ncreds))) {
return (code);
}
/* Now we have all we need to make the change request. */
srvr_msg);
return (result);
}