[1753] in Moira
changes to setpw.c
daemon@ATHENA.MIT.EDU (David E. Tanner)
Mon Mar 19 16:19:13 2001
Message-Id: <3.0.32.20010319161528.0119d008@po14.mit.edu>
Date: Mon, 19 Mar 2001 16:15:29 -0500
To: moiradev@MIT.EDU
From: "David E. Tanner" <dtanner@MIT.EDU>
Mime-Version: 1.0
Content-Type: text/enriched; charset="us-ascii"
<smaller>Below are changes that I had to make to the set password
processing for the WIN2K KDC. There is also some code cleanup.
Index: setpw.c
===================================================================
RCS file:
/afs/athena.mit.edu/astaff/project/moiradev/repository/moira/incremental/winad/setpw.c,v
retrieving revision 1.1
diff -c -r1.1 setpw.c
*** setpw.c 2000/11/11 11:05:49 1.1
--- setpw.c 2001/03/19 19:58:21
***************
*** 359,366 ****
int tmp_len;
int error_count;
krb5_principal targprinc;
! struct timeval TimeVal;
! fd_set readfds;
auth_context = NULL;
addr_p = NULL;
--- 359,366 ----
int tmp_len;
int error_count;
krb5_principal targprinc;
! int count;
! int last_count;
auth_context = NULL;
addr_p = NULL;
***************
*** 401,422 ****
goto cleanup;
}
- /* 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. */
-
if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
free(addr_p);
--- 401,406 ----
***************
*** 433,439 ****
{
if (connect(s2, &addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR)
continue;
-
addrlen = sizeof(local_addr);
if (getsockname(s2, &local_addr, &addrlen) << 0)
continue;
--- 417,422 ----
***************
*** 465,492 ****
sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
remote_kaddr.contents =
(char *) &(((struct sockaddr_in *) &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? */
if (code = krb5_auth_con_setaddrs(context, auth_context,
&local_kaddr, NULL))
goto cleanup;
if (code = krb5_mk_setpw_req(context, auth_context, &ap_req,
targprinc, newpw, &chpw_req))
goto cleanup;
if ((cc = sendto(s1, chpw_req.data, chpw_req.length, 0,
(struct sockaddr *) &addr_p[i],
sizeof(addr_p[i]))) != chpw_req.length)
! continue; /* try the next addr */
#ifdef _WIN32
krb5_free_data_contents(context, &chpw_req);
#else
--- 448,465 ----
sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
remote_kaddr.contents =
(char *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
!
if (code = krb5_auth_con_setaddrs(context, auth_context,
&local_kaddr, NULL))
goto cleanup;
if (code = krb5_mk_setpw_req(context, auth_context, &ap_req,
targprinc, newpw, &chpw_req))
goto cleanup;
+
if ((cc = sendto(s1, chpw_req.data, chpw_req.length, 0,
(struct sockaddr *) &addr_p[i],
sizeof(addr_p[i]))) != chpw_req.length)
! continue;
!
#ifdef _WIN32
krb5_free_data_contents(context, &chpw_req);
#else
***************
*** 494,532 ****
#endif
chpw_rep.length = 1500;
chpw_rep.data = (char *) calloc(1, chpw_rep.length);
- /* XXX need a timeout/retry loop here */
- /* "recv" would be good enough here... except that Windows/NT
- commits the atrocity of returning -1 to indicate failure,
- but leaving errno set to 0.
-
- "recvfrom(...,NULL,NULL)" would seem to be a good enough
- alternative, and it works on NT, but it doesn't work on
- SunOS 4.1.4 or Irix 5.3. Thus we must actually accept the
- value and discard it. */
- tmp_len = sizeof(tmp_addr);
- TimeVal.tv_sec = 10;
- TimeVal.tv_usec = 0;
! FD_ZERO(&readfds);
! FD_SET(s1, &readfds);
! code = select(1, &readfds, NULL, NULL, &TimeVal);
!
! if ((code == 0) || (code == SOCKET_ERROR))
! {
! if (error_count << 2)
! {
! closesocket(s1);
! closesocket(s2);
! if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) ==
INVALID_SOCKET)
! goto cleanup;
! if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) ==
INVALID_SOCKET)
! goto cleanup;
! ++error_count;
! --i;
! continue;
! }
! code = errno;
! goto cleanup;
}
if ((cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, 0,
&tmp_addr, &tmp_len)) << 0)
{
--- 467,488 ----
#endif
chpw_rep.length = 1500;
chpw_rep.data = (char *) calloc(1, chpw_rep.length);
! tmp_len = sizeof(tmp_addr);
! last_count = 0;
! while (1)
! {
! cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, MSG_PEEK,
&tmp_addr, &tmp_len);
! if ((last_count == cc) && (cc != 0))
! break;
! last_count = cc;
! if (cc == 0)
! {
! if (last_count == -1)
! break;
! last_count = -1;
! }
! sleep(1);
}
if ((cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, 0,
&tmp_addr, &tmp_len)) << 0)
{
***************
*** 543,554 ****
code = krb5_rd_setpw_rep(context, auth_context, &chpw_rep,
&local_result_code, &result_string);
! if (result_code)
! *result_code = local_result_code;
#ifdef _WIN32
! krb5_free_data_contents(context, &chpw_req);
#else
! free(chpw_req.data);
#endif
break;
--- 499,514 ----
code = krb5_rd_setpw_rep(context, auth_context, &chpw_rep,
&local_result_code, &result_string);
! if (local_result_code)
! {
! if (local_result_code == KRB5_KPASSWD_SOFTERROR)
! local_result_code = KRB5_KPASSWD_SUCCESS;
! *result_code = local_result_code;
! }
#ifdef _WIN32
! krb5_free_data_contents(context, &chpw_rep);
#else
! free(chpw_rep.data);
#endif
break;
***************
*** 589,599 ****
memset(pw, '\0', sizeof(pw));
generate_password(pw);
retval = krb5_set_password(context, ccache, pw, user, domain,
&res_code);
krb5_cc_close(context, ccache);
krb5_free_context(context);
! return(retval);
}
void generate_password(char *password)
--- 549,562 ----
memset(pw, '\0', sizeof(pw));
generate_password(pw);
+ res_code = 0;
retval = krb5_set_password(context, ccache, pw, user, domain,
&res_code);
krb5_cc_close(context, ccache);
krb5_free_context(context);
! if (retval)
! return(retval);
! return(res_code);
}
void generate_password(char *password)
</smaller>