The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netncp/ncp_ncp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1999, 2000, 2001 Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Boris Popov.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD: releng/5.0/sys/netncp/ncp_ncp.c 104908 2002-10-11 14:58:34Z mike $
   33  *
   34  * Core of NCP protocol
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/errno.h>
   39 #include <sys/systm.h>
   40 #include <sys/proc.h>
   41 #include <sys/signalvar.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/uio.h>
   45 
   46 #include <netipx/ipx.h>
   47 #include <netipx/ipx_var.h>
   48 
   49 #include <netncp/ncp.h>
   50 #include <netncp/ncp_conn.h>
   51 #include <netncp/ncp_sock.h>
   52 #include <netncp/ncp_subr.h>
   53 #include <netncp/ncp_ncp.h>
   54 #include <netncp/ncp_rq.h>
   55 #include <netncp/nwerror.h>
   56 
   57 #ifdef NCP_DATA_DEBUG
   58 static
   59 void m_dumpm(struct mbuf *m) {
   60         char *p;
   61         int len;
   62         printf("d=");
   63         while(m) {
   64                 p=mtod(m,char *);
   65                 len=m->m_len;
   66                 printf("(%d)",len);
   67                 while(len--){
   68                         printf("%02x ",((int)*(p++)) & 0xff);
   69                 }
   70                 m=m->m_next;
   71         };
   72         printf("\n");
   73 }
   74 #endif /* NCP_DATA_DEBUG */
   75 
   76 int
   77 ncp_chkintr(struct ncp_conn *conn, struct proc *p)
   78 {
   79         sigset_t tmpset;
   80 
   81         if (p == NULL)
   82                 return 0;
   83         tmpset = p->p_siglist;
   84         SIGSETNAND(tmpset, p->p_sigmask);
   85         SIGSETNAND(tmpset, p->p_sigignore);
   86         if (SIGNOTEMPTY(p->p_siglist) && NCP_SIGMASK(tmpset))
   87                 return EINTR;
   88         return 0;
   89 }
   90 
   91 /*
   92  * Process initial NCP handshake (attach)
   93  * NOTE: Since all functions below may change conn attributes, they
   94  * should be called with LOCKED connection, also they use procp & ucred
   95  */
   96 int
   97 ncp_ncp_connect(struct ncp_conn *conn)
   98 {
   99         struct ncp_rq *rqp;
  100         struct ncp_rphdr *rp;
  101         int error;
  102         
  103         error = ncp_rq_alloc_any(NCP_ALLOC_SLOT, 0, conn, conn->procp, conn->ucred, &rqp);
  104         if (error)
  105                 return error;
  106 
  107         conn->flags &= ~(NCPFL_SIGNACTIVE | NCPFL_SIGNWANTED |
  108             NCPFL_ATTACHED | NCPFL_LOGGED | NCPFL_INVALID);
  109         conn->seq = 0;
  110         error = ncp_request_int(rqp);
  111         if (!error) {
  112                 rp = mtod(rqp->rp.md_top, struct ncp_rphdr*);
  113                 conn->connid = rp->conn_low + (rp->conn_high << 8);
  114         }
  115         ncp_rq_done(rqp);
  116         if (error)
  117                 return error;
  118         conn->flags |= NCPFL_ATTACHED | NCPFL_WASATTACHED;
  119         return 0;
  120 }
  121 
  122 int
  123 ncp_ncp_disconnect(struct ncp_conn *conn)
  124 {
  125         struct ncp_rq *rqp;
  126         int error;
  127 
  128         NCPSDEBUG("for connid=%d\n",conn->nc_id);
  129 #ifdef NCPBURST
  130         ncp_burst_disconnect(conn);
  131 #endif
  132         if (conn->flags & NCPFL_ATTACHED) {
  133                 error = ncp_rq_alloc_any(NCP_FREE_SLOT, 0, conn, conn->procp, conn->ucred, &rqp);
  134                 if (!error) {
  135                         ncp_request_int(rqp);
  136                         ncp_rq_done(rqp);
  137                 }
  138         }
  139         ncp_conn_invalidate(conn);
  140         ncp_sock_disconnect(conn);
  141         return 0;
  142 }
  143 
  144 /*
  145  * All negotiation functions expect a locked connection
  146  */
  147 
  148 int
  149 ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target)
  150 {
  151         struct ncp_rq *rqp;
  152         u_int16_t bsize;
  153         int error;
  154 
  155         error = ncp_rq_alloc(0x21, conn, conn->procp, conn->ucred, &rqp);
  156         if (error)
  157                 return error;
  158         mb_put_uint16be(&rqp->rq, size);
  159         error = ncp_request(rqp);
  160         if (error)
  161                 return error;
  162         md_get_uint16be(&rqp->rp, &bsize);
  163         *target = min(bsize, size);
  164         ncp_rq_done(rqp);
  165         return error;
  166 }
  167 
  168 static int
  169 ncp_negotiate_size_and_options(struct ncp_conn *conn, int size, int options, 
  170             int *ret_size, u_int8_t *ret_options)
  171 {
  172         struct ncp_rq *rqp;
  173         u_int16_t rs;
  174         int error;
  175 
  176         error = ncp_rq_alloc(0x61, conn, conn->procp, conn->ucred, &rqp);
  177         if (error)
  178                 return error;
  179         mb_put_uint16be(&rqp->rq, size);
  180         mb_put_uint8(&rqp->rq, options);
  181         rqp->nr_minrplen = 2 + 2 + 1;
  182         error = ncp_request(rqp);
  183         if (error)
  184                 return error;
  185         md_get_uint16be(&rqp->rp, &rs);
  186         *ret_size = (rs == 0) ? size : min(rs, size);
  187         md_get_uint16be(&rqp->rp, &rs);         /* skip echo socket */
  188         md_get_uint8(&rqp->rp, ret_options);
  189         ncp_rq_done(rqp);
  190         return error;
  191 }
  192 
  193 int
  194 ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, u_int8_t in_options)
  195 {
  196         u_int8_t options;
  197         int neg_buffsize, error, sl, ckslevel, ilen;
  198 
  199         sl = conn->li.sig_level;
  200         if (sl >= 2)
  201                 in_options |= NCP_SECURITY_LEVEL_SIGN_HEADERS;
  202         if (conn->li.saddr.sa_family == AF_IPX) {
  203                 ilen = sizeof(ckslevel);
  204                 error = kernel_sysctlbyname(curproc, "net.ipx.ipx.checksum",
  205                     &ckslevel, &ilen, NULL, 0, NULL);
  206                 if (error)
  207                         return error;
  208                 if (ckslevel == 2)
  209                         in_options |= NCP_IPX_CHECKSUM;
  210         }
  211         error = ncp_negotiate_size_and_options(conn, buffsize, in_options, 
  212             &neg_buffsize, &options);
  213         if (!error) {
  214                 if (conn->li.saddr.sa_family == AF_IPX &&
  215                     ((options ^ in_options) & NCP_IPX_CHECKSUM)) {
  216                         if (ckslevel == 2) {
  217                                 printf("Server refuses to support IPX checksums\n");
  218                                 return NWE_REQUESTER_FAILURE;
  219                         }
  220                         in_options |= NCP_IPX_CHECKSUM;
  221                         error = 1;
  222                 }
  223                 if ((options ^ in_options) & 2) {
  224                         if (sl == 0 || sl == 3)
  225                                 return NWE_SIGNATURE_LEVEL_CONFLICT;
  226                         if (sl == 1) {
  227                                 in_options |= NCP_SECURITY_LEVEL_SIGN_HEADERS;
  228                                 error = 1;
  229                         }
  230                 }
  231                 if (error) {
  232                         error = ncp_negotiate_size_and_options(conn,
  233                             buffsize, in_options, &neg_buffsize, &options);
  234                         if ((options ^ in_options) & 3) {
  235                                 return NWE_SIGNATURE_LEVEL_CONFLICT;
  236                         }
  237                 }
  238         } else {
  239                 in_options &= ~NCP_SECURITY_LEVEL_SIGN_HEADERS;
  240                 error = ncp_negotiate_buffersize(conn, NCP_DEFAULT_BUFSIZE,
  241                               &neg_buffsize);
  242         }                         
  243         if (error) return error;
  244         if ((neg_buffsize < 512) || (neg_buffsize > NCP_MAX_BUFSIZE))
  245                 return EINVAL;
  246         conn->buffer_size = neg_buffsize;
  247         if (in_options & NCP_SECURITY_LEVEL_SIGN_HEADERS)
  248                 conn->flags |= NCPFL_SIGNWANTED;
  249         if (conn->li.saddr.sa_family == AF_IPX)
  250                 ncp_sock_checksum(conn, in_options & NCP_IPX_CHECKSUM);
  251         return 0;
  252 }
  253 
  254 void
  255 ncp_check_rq(struct ncp_conn *conn){
  256         return;
  257         if (conn->flags & NCPFL_INTR) return;
  258         /* first, check for signals */
  259         if (ncp_chkintr(conn,conn->procp)) {
  260                 conn->flags |= NCPFL_INTR;
  261         }
  262         return;
  263 }
  264 
  265 int
  266 ncp_get_bindery_object_id(struct ncp_conn *conn, 
  267                 u_int16_t object_type, char *object_name, 
  268                 struct ncp_bindery_object *target,
  269                 struct proc *p,struct ucred *cred)
  270 {
  271         struct ncp_rq *rqp;
  272         int error;
  273 
  274         error = ncp_rq_alloc_subfn(23, 53, conn, conn->procp, conn->ucred, &rqp);
  275         mb_put_uint16be(&rqp->rq, object_type);
  276         ncp_rq_pstring(rqp, object_name);
  277         rqp->nr_minrplen = 54;
  278         error = ncp_request(rqp);
  279         if (error)
  280                 return error;
  281         md_get_uint32be(&rqp->rp, &target->object_id);
  282         md_get_uint16be(&rqp->rp, &target->object_type);
  283         md_get_mem(&rqp->rp, (caddr_t)target->object_name, 48, MB_MSYSTEM);
  284         ncp_rq_done(rqp);
  285         return 0;
  286 }
  287 
  288 /*
  289  * target is a 8-byte buffer
  290  */
  291 int
  292 ncp_get_encryption_key(struct ncp_conn *conn, char *target)
  293 {
  294         struct ncp_rq *rqp;
  295         int error;
  296 
  297         error = ncp_rq_alloc_subfn(23, 23, conn, conn->procp, conn->ucred, &rqp);
  298         if (error)
  299                 return error;
  300         rqp->nr_minrplen = 8;
  301         error = ncp_request(rqp);
  302         if (error)
  303                 return error;
  304         md_get_mem(&rqp->rp, target, 8, MB_MSYSTEM);
  305         ncp_rq_done(rqp);
  306         return error;
  307 }
  308 
  309 /*
  310  * Initialize packet signatures. They a slightly modified MD4.
  311  * The first 16 bytes of logindata are the shuffled password,
  312  * the last 8 bytes the encryption key as received from the server.
  313  */
  314 static int
  315 ncp_sign_start(struct ncp_conn *conn, char *logindata)
  316 {
  317         char msg[64];
  318         u_int32_t state[4];
  319 
  320         memcpy(msg, logindata, 24);
  321         memcpy(msg + 24, "Authorized NetWare Client", 25);
  322         bzero(msg + 24 + 25, sizeof(msg) - 24 - 25);
  323 
  324         conn->sign_state[0] = 0x67452301;
  325         conn->sign_state[1] = 0xefcdab89;
  326         conn->sign_state[2] = 0x98badcfe;
  327         conn->sign_state[3] = 0x10325476;
  328         ncp_sign(conn->sign_state, msg, state);
  329         conn->sign_root[0] = state[0];
  330         conn->sign_root[1] = state[1];
  331         conn->flags |= NCPFL_SIGNACTIVE;
  332         return 0;
  333 }
  334 
  335 
  336 int
  337 ncp_login_encrypted(struct ncp_conn *conn, struct ncp_bindery_object *object,
  338         const u_char *key, const u_char *passwd,
  339         struct proc *p, struct ucred *cred)
  340 {
  341         struct ncp_rq *rqp;
  342         struct mbchain *mbp;
  343         u_int32_t tmpID = htonl(object->object_id);
  344         u_char buf[16 + 8];
  345         u_char encrypted[8];
  346         int error;
  347 
  348         nw_keyhash((u_char*)&tmpID, passwd, strlen(passwd), buf);
  349         nw_encrypt(key, buf, encrypted);
  350 
  351         error = ncp_rq_alloc_subfn(23, 24, conn, p, cred, &rqp);
  352         if (error)
  353                 return error;
  354         mbp = &rqp->rq;
  355         mb_put_mem(mbp, encrypted, 8, MB_MSYSTEM);
  356         mb_put_uint16be(mbp, object->object_type);
  357         ncp_rq_pstring(rqp, object->object_name);
  358         error = ncp_request(rqp);
  359         if (!error)
  360                 ncp_rq_done(rqp);
  361         if ((conn->flags & NCPFL_SIGNWANTED) &&
  362             (error == 0 || error == NWE_PASSWORD_EXPIRED)) {
  363                 bcopy(key, buf + 16, 8);
  364                 error = ncp_sign_start(conn, buf);
  365         }
  366         return error;
  367 }
  368 
  369 int
  370 ncp_login_unencrypted(struct ncp_conn *conn, u_int16_t object_type, 
  371         const char *object_name, const u_char *passwd,
  372         struct proc *p, struct ucred *cred)
  373 {
  374         struct ncp_rq *rqp;
  375         int error;
  376 
  377         error = ncp_rq_alloc_subfn(23, 20, conn, p, cred, &rqp);
  378         if (error)
  379                 return error;
  380         mb_put_uint16be(&rqp->rq, object_type);
  381         ncp_rq_pstring(rqp, object_name);
  382         ncp_rq_pstring(rqp, passwd);
  383         error = ncp_request(rqp);
  384         if (!error)
  385                 ncp_rq_done(rqp);
  386         return error;
  387 }
  388 
  389 int
  390 ncp_read(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
  391 {
  392         struct ncp_rq *rqp;
  393         struct mbchain *mbp;
  394         u_int16_t retlen = 0 ;
  395         int error = 0, len = 0, tsiz, burstio;
  396 
  397         tsiz = uiop->uio_resid;
  398 #ifdef NCPBURST
  399         burstio = (ncp_burst_enabled && tsiz > conn->buffer_size);
  400 #else
  401         burstio = 0;
  402 #endif
  403 
  404         while (tsiz > 0) {
  405                 if (!burstio) {
  406                         len = min(4096 - (uiop->uio_offset % 4096), tsiz);
  407                         len = min(len, conn->buffer_size);
  408                         error = ncp_rq_alloc(72, conn, uiop->uio_procp, cred, &rqp);
  409                         if (error)
  410                                 break;
  411                         mbp = &rqp->rq;
  412                         mb_put_uint8(mbp, 0);
  413                         mb_put_mem(mbp, (caddr_t)file, 6, MB_MSYSTEM);
  414                         mb_put_uint32be(mbp, uiop->uio_offset);
  415                         mb_put_uint16be(mbp, len);
  416                         rqp->nr_minrplen = 2;
  417                         error = ncp_request(rqp);
  418                         if (error)
  419                                 break;
  420                         md_get_uint16be(&rqp->rp, &retlen);
  421                         if (uiop->uio_offset & 1)
  422                                 md_get_mem(&rqp->rp, NULL, 1, MB_MSYSTEM);
  423                         error = md_get_uio(&rqp->rp, uiop, retlen);
  424                         ncp_rq_done(rqp);
  425                 } else {
  426 #ifdef NCPBURST
  427                         error = ncp_burst_read(conn, file, tsiz, &len, &retlen, uiop, cred);
  428 #endif
  429                 }
  430                 if (error)
  431                         break;
  432                 tsiz -= retlen;
  433                 if (retlen < len)
  434                         break;
  435         }
  436         return (error);
  437 }
  438 
  439 int
  440 ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *cred)
  441 {
  442         struct ncp_rq *rqp;
  443         struct mbchain *mbp;
  444         int error = 0, len, tsiz, backup;
  445 
  446         if (uiop->uio_iovcnt != 1) {
  447                 printf("%s: can't handle iovcnt>1 !!!\n", __func__);
  448                 return EIO;
  449         }
  450         tsiz = uiop->uio_resid;
  451         while (tsiz > 0) {
  452                 len = min(4096 - (uiop->uio_offset % 4096), tsiz);
  453                 len = min(len, conn->buffer_size);
  454                 if (len == 0) {
  455                         printf("gotcha!\n");
  456                 }
  457                 /* rq head */
  458                 error = ncp_rq_alloc(73, conn, uiop->uio_procp, cred, &rqp);
  459                 if (error)
  460                         break;
  461                 mbp = &rqp->rq;
  462                 mb_put_uint8(mbp, 0);
  463                 mb_put_mem(mbp, (caddr_t)file, 6, MB_MSYSTEM);
  464                 mb_put_uint32be(mbp, uiop->uio_offset);
  465                 mb_put_uint16be(mbp, len);
  466                 error = mb_put_uio(mbp, uiop, len);
  467                 if (error) {
  468                         ncp_rq_done(rqp);
  469                         break;
  470                 }
  471                 error = ncp_request(rqp);
  472                 if (!error)
  473                         ncp_rq_done(rqp);
  474                 if (len == 0)
  475                         break;
  476                 if (error) {
  477                         backup = len;
  478                         uiop->uio_iov->iov_base =
  479                             (char *)uiop->uio_iov->iov_base - backup;
  480                         uiop->uio_iov->iov_len += backup;
  481                         uiop->uio_offset -= backup;
  482                         uiop->uio_resid += backup;
  483                         break;
  484                 }
  485                 tsiz -= len;
  486         }
  487         if (error)
  488                 uiop->uio_resid = tsiz;
  489         switch (error) {
  490             case NWE_INSUFFICIENT_SPACE:
  491                 error = ENOSPC;
  492                 break;
  493         }
  494         return (error);
  495 }

Cache object: af09f6dde01fb7a45b85585361c88570


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.