/*
*/
/*
*
* Copyright 1998 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.
*
*/
/*
* chgpwd.c - Handles changepw requests issued from non-Solaris krb5 clients.
*/
/* Solaris Kerberos */
#include "k5-int.h"
#include <errno.h>
#include <string.h>
#include <libintl.h>
#include <locale.h>
#include <syslog.h>
#include <krb5/adm_proto.h>
static krb5_error_code
{
char *ptr;
int allocated_mem = 0;
int numresult;
char *cdots;
ret = 0;
auth_context = NULL;
/*
* either this, or the server is printing bad messages,
* or the caller passed in garbage
*/
sizeof (strresult));
goto chpwfail;
}
/*
* Verify length
*/
return (KRB5KRB_AP_ERR_MODIFIED);
/*
* Verify version number
*/
"Request contained unknown protocol version number %d",
vno);
goto chpwfail;
}
/*
* Read, check ap-req length
*/
sizeof (strresult));
goto chpwfail;
}
/*
* Verify ap_req
*/
gettext("Change password request failed. "
"Failed initializing auth context: %s"),
error_message(ret));
sizeof (strresult));
goto chpwfail;
}
gettext("Change password request failed. "
"Failed setting auth "
"context flags: %s"),
error_message(ret));
sizeof (strresult));
goto chpwfail;
}
gettext("Change password request failed "
"principal: %s"),
error_message(ret));
sizeof (strresult));
goto chpwfail;
}
if (ret) {
switch (ret) {
case KRB5_KT_NOTFOUND:
gettext("Change password request failed because "
"is missing from \"%s\""),
kt_name);
break;
case ENOENT:
gettext("Change password request failed because "
"keytab file \"%s\" does not exist"),
kt_name);
break;
default:
gettext("Change password request failed. "
"Failed to parse Kerberos AP_REQ message: %s"),
error_message(ret));
}
sizeof (strresult));
goto chpwfail;
}
/*
* Set up address info
*/
addrlen = sizeof (local_addr);
"Failed getting server internet address",
sizeof (strresult));
goto chpwfail;
}
/*
* Some brain-dead OS's don't return useful information from
* the getsockname call. Namely, windows and solaris.
*/
&local_addr)->sin_addr);
/* CSTYLED */
} else {
"Malloc failed for local_kaddr",
sizeof (strresult));
goto chpwfail;
}
}
addrlen = sizeof (remote_addr);
"Failed getting client internet address",
sizeof (strresult));
goto chpwfail;
}
&remote_addr)->sin_addr);
/* CSTYLED */
/*
* 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?
*/
&remote_kaddr)) {
"Failed storing client internet address",
sizeof (strresult));
goto chpwfail;
}
/*
* Construct the ap-rep
*/
"Failed replying to application request",
sizeof (strresult));
goto chpwfail;
}
/*
* Decrypt the new password
*/
sizeof (strresult));
goto chpwfail;
}
/* decode ChangePasswdData for setpw requests */
if (vno == RFC3244_VERSION) {
if (ret != 0) {
sizeof(strresult));
goto chpwfail;
}
clear = *clear_data;
if (ret != 0) {
sizeof(strresult));
goto chpwfail;
}
}
}
if (ret) {
goto chpwfail;
}
/* for cpw, verify that this is an AS_REQ ticket */
if (vno == 1 &&
sizeof(strresult));
goto chpwfail;
}
/*
* Change the password
*/
sizeof (strresult));
goto chpwfail;
}
/*
* Zap the password
*/
}
if (vno == RFC3244_VERSION) {
char *tdots;
const char *targetp;
} else {
}
"for %.*s%s: %s",
} else {
}
switch (ret) {
case KADM5_AUTH_CHANGEPW:
break;
case KADM5_PASS_Q_TOOSHORT:
case KADM5_PASS_REUSE:
case KADM5_PASS_Q_CLASS:
case KADM5_PASS_Q_DICT:
case KADM5_PASS_TOOSOON:
break;
case 0:
break;
default:
break;
}
}
sizeof (strresult));
}
&local_kaddr, NULL)) {
"Failed storing client and server internet addresses",
sizeof (strresult));
} else {
"Failed encrypting reply",
sizeof (strresult));
}
}
}
/*
* If no KRB-PRIV was constructed, then we need a KRB-ERROR.
* If this fails, just bail. There's nothing else we can do.
*/
/*
* Clear out ap_rep now, so that it won't be inserted
* in the reply
*/
}
goto bailout;
/*
* This is really icky. but it's what all the other callers
* to mk_error do.
*/
goto bailout;
}
if (ret)
goto bailout;
}
/*
* Construct the reply
*/
goto bailout;
}
/*
* Length
*/
/*
* Version == 0x0001 big-endian
*/
*ptr++ = 0;
*ptr++ = 1;
/*
* ap_rep length, big-endian
*/
/*
* ap-rep data
*/
}
/*
* krb-priv or krb-error
*/
if (auth_context)
if (changepw)
if (ticket)
if (allocated_mem)
if (target)
if (targetstr)
if (clientstr)
return (ret);
}
/*
* This routine is used to handle password-change requests received
* on kpasswd-port 464 from MIT/M$ clients.
*/
void
{
int len;
&fromlen)) < 0) {
return;
}
/*
* Solaris Kerberos:
* The only caller is kadmind, which is the master and therefore has the
* correct keys in the KDB, rather than obtaining them via the
* kadm5.keytab, by default.
*/
return;
}
/*
* 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;
}
if (s2 > 0)
goto cleanup;
}
}
if (s2 > 0)
/*
* Just return. This means something really bad happened
*/
goto cleanup;
}
goto cleanup;
}
}