From 73834ced9f7a48ef9945ce9c3e36fa3be0e846f9 Mon Sep 17 00:00:00 2001 From: Boris Popov Date: Thu, 22 Mar 2001 10:38:16 +0000 Subject: [PATCH] Move bindery authentication ncps to ncp_ncp.c file. ncp_login.c will stay empty for a while. --- sys/netncp/ncp_conn.c | 25 +++++++ sys/netncp/ncp_conn.h | 1 + sys/netncp/ncp_login.c | 160 ----------------------------------------- sys/netncp/ncp_mod.c | 44 +++++++++++- sys/netncp/ncp_ncp.c | 101 ++++++++++++++++++++++++++ sys/netncp/ncp_ncp.h | 13 ++-- sys/netncp/ncp_rq.c | 4 +- 7 files changed, 178 insertions(+), 170 deletions(-) diff --git a/sys/netncp/ncp_conn.c b/sys/netncp/ncp_conn.c index c40552b8fc4..f1f6983db24 100644 --- a/sys/netncp/ncp_conn.c +++ b/sys/netncp/ncp_conn.c @@ -352,6 +352,31 @@ ncp_conn_reconnect(struct ncp_conn *ncp) return 0; } +int +ncp_conn_login(struct ncp_conn *conn, struct proc *p, struct ucred *cred) +{ + struct ncp_bindery_object user; + u_char ncp_key[8]; + int error; + + error = ncp_get_encryption_key(conn, ncp_key); + if (error) { + printf("%s: Warning: use unencrypted login\n", __FUNCTION__); + error = ncp_login_unencrypted(conn, conn->li.objtype, + conn->li.user, conn->li.password, p, cred); + } else { + error = ncp_get_bindery_object_id(conn, conn->li.objtype, + conn->li.user, &user, p, cred); + if (error) + return error; + error = ncp_login_encrypted(conn, &user, ncp_key, + conn->li.password, p, cred); + } + if (!error) + conn->flags |= NCPFL_LOGGED | NCPFL_WASLOGGED; + return error; +} + /* * Lookup connection by handle, return a locked conn descriptor */ diff --git a/sys/netncp/ncp_conn.h b/sys/netncp/ncp_conn.h index 26b455c25e3..707cac0d16f 100644 --- a/sys/netncp/ncp_conn.h +++ b/sys/netncp/ncp_conn.h @@ -221,6 +221,7 @@ int ncp_conn_putprochandles(struct proc *p); int ncp_conn_getinfo(struct ncp_conn *ncp, struct ncp_conn_stat *ncs); int ncp_conn_reconnect(struct ncp_conn *ncp); +int ncp_conn_login(struct ncp_conn *conn, struct proc *p, struct ucred *cred); extern struct ncp_conn_head conn_list; extern int ncp_burst_enabled; diff --git a/sys/netncp/ncp_login.c b/sys/netncp/ncp_login.c index b7e76c7788b..8cd347b2fef 100644 --- a/sys/netncp/ncp_login.c +++ b/sys/netncp/ncp_login.c @@ -46,163 +46,3 @@ #include #include -static int ncp_login_encrypted(struct ncp_conn *conn, struct ncp_bindery_object *object, - unsigned char *key, unsigned char *passwd, - struct proc *p, struct ucred *cred); -static int ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type, - char *object_name, unsigned char *passwd, - struct proc *p, struct ucred *cred); -static int ncp_sign_start(struct ncp_conn *conn, char *logindata); -static int ncp_get_encryption_key(struct ncp_conn *conn, char *target); - -/* - * Initialize packet signatures. They a slightly modified MD4. - * The first 16 bytes of logindata are the shuffled password, - * the last 8 bytes the encryption key as received from the server. - */ -int -ncp_sign_start(struct ncp_conn *conn, char *logindata) { - char msg[64]; - u_int32_t state[4]; - - memcpy(msg, logindata, 24); - memcpy(msg + 24, "Authorized NetWare Client", 25); - bzero(msg + 24 + 25, sizeof(msg) - 24 - 25); - - conn->sign_state[0] = 0x67452301; - conn->sign_state[1] = 0xefcdab89; - conn->sign_state[2] = 0x98badcfe; - conn->sign_state[3] = 0x10325476; - ncp_sign(conn->sign_state, msg, state); - conn->sign_root[0] = state[0]; - conn->sign_root[1] = state[1]; - conn->flags |= NCPFL_SIGNACTIVE; - return 0; -} - -/* - * target is a 8-byte buffer - */ -int -ncp_get_encryption_key(struct ncp_conn *conn, char *target) -{ - struct ncp_rq *rqp; - int error; - - error = ncp_rq_alloc_subfn(23, 23, conn, conn->procp, conn->ucred, &rqp); - if (error) - return error; - rqp->nr_minrplen = 8; - error = ncp_request(rqp); - if (error) - return error; - md_get_mem(&rqp->rp, target, 8, MB_MSYSTEM); - ncp_rq_done(rqp); - return error; -} - -int -ncp_login_object(struct ncp_conn *conn, unsigned char *username, - int login_type, unsigned char *password, - struct proc *p,struct ucred *cred) -{ - int error; - unsigned char ncp_key[8]; - struct ncp_bindery_object user; - - if ((error = ncp_get_encryption_key(conn, ncp_key)) != 0) { - printf("%s: Warning: use unencrypted login\n", __FUNCTION__); - return ncp_login_unencrypted(conn, login_type, username, password,p,cred); - } - if ((error = ncp_get_bindery_object_id(conn, login_type, username, &user,p,cred)) != 0) { - return error; - } - error = ncp_login_encrypted(conn, &user, ncp_key, password,p,cred); - return error; -} - -int -ncp_login_encrypted(struct ncp_conn *conn, struct ncp_bindery_object *object, - unsigned char *key, unsigned char *passwd, - struct proc *p,struct ucred *cred) -{ - struct ncp_rq *rqp; - struct mbchain *mbp; - u_int32_t tmpID = htonl(object->object_id); - u_char buf[16 + 8]; - u_char encrypted[8]; - int error; - - nw_keyhash((u_char*)&tmpID, passwd, strlen(passwd), buf); - nw_encrypt(key, buf, encrypted); - - error = ncp_rq_alloc_subfn(23, 24, conn, p, cred, &rqp); - if (error) - return error; - mbp = &rqp->rq; - mb_put_mem(mbp, encrypted, 8, MB_MSYSTEM); - mb_put_uint16be(mbp, object->object_type); - ncp_rq_pstring(rqp, object->object_name); - error = ncp_request(rqp); - if (!error) - ncp_rq_done(rqp); - if ((conn->flags & NCPFL_SIGNWANTED) && - (error == 0 || error == NWE_PASSWORD_EXPIRED)) { - bcopy(key, buf + 16, 8); - error = ncp_sign_start(conn, buf); - } - return error; -} - -int -ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type, - char *object_name, unsigned char *passwd, - struct proc *p, struct ucred *cred) -{ - struct ncp_rq *rqp; - int error; - - error = ncp_rq_alloc_subfn(23, 20, conn, p, cred, &rqp); - if (error) - return error; - mb_put_uint16be(&rqp->rq, object_type); - ncp_rq_pstring(rqp, object_name); - ncp_rq_pstring(rqp, passwd); - error = ncp_request(rqp); - if (!error) - ncp_rq_done(rqp); - return error; -} - -/* - * Login to specified server with username and password. - * conn should be locked. - */ -int -ncp_login(struct ncp_conn *conn, char *user, int objtype, char *password, - struct proc *p, struct ucred *cred) { - int error; - - if (ncp_suser(cred) != 0 && cred->cr_uid != conn->nc_owner->cr_uid) - return EACCES; - if (conn->flags & NCPFL_LOGGED) return EALREADY; - if ((conn->flags & NCPFL_ATTACHED) == 0) return ENOTCONN; - conn->li.user = ncp_str_dup(user); - conn->li.password = ncp_str_dup(password); - if (conn->li.user == NULL || conn->li.password == NULL) { - error = EINVAL; - goto bad; - } - ncp_str_upper(conn->li.user); - if ((conn->li.opt & NCP_OPT_NOUPCASEPASS) == 0) - ncp_str_upper(conn->li.password); - checkbad(ncp_login_object(conn, conn->li.user, objtype, conn->li.password,p,cred)); - conn->li.objtype = objtype; - conn->flags |= NCPFL_LOGGED | NCPFL_WASLOGGED; - return 0; -bad: - if (conn->li.user) free(conn->li.user, M_NCPDATA); - if (conn->li.password) free(conn->li.password, M_NCPDATA); - conn->li.user = conn->li.password = NULL; - return error; -} diff --git a/sys/netncp/ncp_mod.c b/sys/netncp/ncp_mod.c index ee8d995abd6..913ec42fcce 100644 --- a/sys/netncp/ncp_mod.c +++ b/sys/netncp/ncp_mod.c @@ -149,6 +149,40 @@ sncp_request(struct proc *p, struct sncp_request_args *uap) return error; } +static int +ncp_mod_login(struct ncp_conn *conn, char *user, int objtype, char *password, + struct proc *p, struct ucred *cred) +{ + int error; + + if (ncp_suser(cred) != 0 && cred->cr_uid != conn->nc_owner->cr_uid) + return EACCES; + conn->li.user = ncp_str_dup(user); + if (conn->li.user == NULL) + return ENOMEM; + conn->li.password = ncp_str_dup(password); + if (conn->li.password == NULL) { + error = ENOMEM; + goto bad; + } + ncp_str_upper(conn->li.user); + if ((conn->li.opt & NCP_OPT_NOUPCASEPASS) == 0) + ncp_str_upper(conn->li.password); + conn->li.objtype = objtype; + error = ncp_conn_login(conn, p, cred); + return error; +bad: + if (conn->li.user) { + free(conn->li.user, M_NCPDATA); + conn->li.user = NULL; + } + if (conn->li.password) { + free(conn->li.password, M_NCPDATA); + conn->li.password = NULL; + } + return error; +} + static int ncp_conn_handler(struct proc *p, struct sncp_request_args *uap, struct ncp_conn *conn, struct ncp_handle *hp) @@ -218,11 +252,15 @@ ncp_conn_handler(struct proc *p, struct sncp_request_args *uap, case NCP_CONN_LOGIN: { struct ncp_conn_login la; - if (rqsize != sizeof(la)) return (EBADRPC); - if ((error = copyin(pdata,&la,rqsize)) != 0) break; + if (rqsize != sizeof(la)) + return EBADRPC; + if (conn->flags & NCPFL_LOGGED) + return EALREADY; + if ((error = copyin(pdata,&la,rqsize)) != 0) + break; error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE | NCPM_WRITE); if (error) return error; - error = ncp_login(conn, la.username, la.objtype, la.password, p, p->p_ucred); + error = ncp_mod_login(conn, la.username, la.objtype, la.password, p, p->p_ucred); ncp_conn_unlock(conn, p); p->p_retval[0] = error; break; diff --git a/sys/netncp/ncp_ncp.c b/sys/netncp/ncp_ncp.c index d29c1e9ba54..172248c1d2a 100644 --- a/sys/netncp/ncp_ncp.c +++ b/sys/netncp/ncp_ncp.c @@ -284,6 +284,107 @@ ncp_get_bindery_object_id(struct ncp_conn *conn, return 0; } +/* + * target is a 8-byte buffer + */ +int +ncp_get_encryption_key(struct ncp_conn *conn, char *target) +{ + struct ncp_rq *rqp; + int error; + + error = ncp_rq_alloc_subfn(23, 23, conn, conn->procp, conn->ucred, &rqp); + if (error) + return error; + rqp->nr_minrplen = 8; + error = ncp_request(rqp); + if (error) + return error; + md_get_mem(&rqp->rp, target, 8, MB_MSYSTEM); + ncp_rq_done(rqp); + return error; +} + +/* + * Initialize packet signatures. They a slightly modified MD4. + * The first 16 bytes of logindata are the shuffled password, + * the last 8 bytes the encryption key as received from the server. + */ +static int +ncp_sign_start(struct ncp_conn *conn, char *logindata) +{ + char msg[64]; + u_int32_t state[4]; + + memcpy(msg, logindata, 24); + memcpy(msg + 24, "Authorized NetWare Client", 25); + bzero(msg + 24 + 25, sizeof(msg) - 24 - 25); + + conn->sign_state[0] = 0x67452301; + conn->sign_state[1] = 0xefcdab89; + conn->sign_state[2] = 0x98badcfe; + conn->sign_state[3] = 0x10325476; + ncp_sign(conn->sign_state, msg, state); + conn->sign_root[0] = state[0]; + conn->sign_root[1] = state[1]; + conn->flags |= NCPFL_SIGNACTIVE; + return 0; +} + + +int +ncp_login_encrypted(struct ncp_conn *conn, struct ncp_bindery_object *object, + const u_char *key, const u_char *passwd, + struct proc *p, struct ucred *cred) +{ + struct ncp_rq *rqp; + struct mbchain *mbp; + u_int32_t tmpID = htonl(object->object_id); + u_char buf[16 + 8]; + u_char encrypted[8]; + int error; + + nw_keyhash((u_char*)&tmpID, passwd, strlen(passwd), buf); + nw_encrypt(key, buf, encrypted); + + error = ncp_rq_alloc_subfn(23, 24, conn, p, cred, &rqp); + if (error) + return error; + mbp = &rqp->rq; + mb_put_mem(mbp, encrypted, 8, MB_MSYSTEM); + mb_put_uint16be(mbp, object->object_type); + ncp_rq_pstring(rqp, object->object_name); + error = ncp_request(rqp); + if (!error) + ncp_rq_done(rqp); + if ((conn->flags & NCPFL_SIGNWANTED) && + (error == 0 || error == NWE_PASSWORD_EXPIRED)) { + bcopy(key, buf + 16, 8); + error = ncp_sign_start(conn, buf); + } + return error; +} + +int +ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type, + const char *object_name, const u_char *passwd, + struct proc *p, struct ucred *cred) +{ + struct ncp_rq *rqp; + int error; + + error = ncp_rq_alloc_subfn(23, 20, conn, p, cred, &rqp); + if (error) + return error; + mb_put_uint16be(&rqp->rq, object_type); + ncp_rq_pstring(rqp, object_name); + ncp_rq_pstring(rqp, passwd); + error = ncp_request(rqp); + if (!error) + ncp_rq_done(rqp); + return error; +} + int ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred) { diff --git a/sys/netncp/ncp_ncp.h b/sys/netncp/ncp_ncp.h index 779350b7341..d715399b83d 100644 --- a/sys/netncp/ncp_ncp.h +++ b/sys/netncp/ncp_ncp.h @@ -113,8 +113,6 @@ struct ucred; int ncp_ncp_connect(struct ncp_conn *conn); int ncp_ncp_disconnect(struct ncp_conn *conn); -int ncp_login(struct ncp_conn *conn, char *user, int objtype, char *password, - struct proc *p, struct ucred *cred); int ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target); int ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, u_int8_t in_options); @@ -122,9 +120,14 @@ int ncp_get_bindery_object_id(struct ncp_conn *conn, u_int16_t object_type, char *object_name, struct ncp_bindery_object *target, struct proc *p,struct ucred *cred); -int ncp_login_object(struct ncp_conn *conn, unsigned char *username, - int login_type, unsigned char *password, - struct proc *p,struct ucred *cred); +int ncp_get_encryption_key(struct ncp_conn *conn, char *target); +int ncp_login_encrypted(struct ncp_conn *conn, + struct ncp_bindery_object *object, + const u_char *key, const u_char *passwd, + struct proc *p, struct ucred *cred); +int ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type, + const char *object_name, const u_char *passwd, + struct proc *p, struct ucred *cred); int ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred); int ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred); diff --git a/sys/netncp/ncp_rq.c b/sys/netncp/ncp_rq.c index 3745bef1fe5..123d2084bd3 100644 --- a/sys/netncp/ncp_rq.c +++ b/sys/netncp/ncp_rq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2000, 2001 Boris Popov + * Copyright (c) 1999-2001 Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -421,7 +421,7 @@ ncp_restore_login(struct ncp_conn *conn) conn->flags |= NCPFL_RESTORING; error = ncp_conn_reconnect(conn); if (!error && (conn->flags & NCPFL_WASLOGGED)) - error = ncp_login_object(conn, conn->li.user, conn->li.objtype, conn->li.password,conn->procp,conn->ucred); + error = ncp_conn_login(conn, conn->procp, conn->ucred); if (error) ncp_ncp_disconnect(conn); conn->flags &= ~NCPFL_RESTORING; -- 2.45.2