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_mod.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) 2003 Tim J. Robbins.
    3  * Copyright (c) 1999, 2000, 2001 Boris Popov
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *    This product includes software developed by Boris Popov.
   17  * 4. Neither the name of the author nor the names of any co-contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/conf.h>
   40 #include <sys/priv.h>
   41 #include <sys/proc.h>
   42 #include <sys/kernel.h>
   43 #include <sys/module.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/malloc.h>
   46 #include <sys/uio.h>
   47 #include <sys/ioccom.h>
   48 
   49 #include <netncp/ncp.h>
   50 #include <netncp/ncp_conn.h>
   51 #include <netncp/ncp_subr.h>
   52 #include <netncp/ncp_ncp.h>
   53 #include <netncp/ncp_user.h>
   54 #include <netncp/ncp_rq.h>
   55 #include <netncp/ncp_nls.h>
   56 #include <netncp/ncpio.h>
   57 
   58 int ncp_version = NCP_VERSION;
   59 
   60 SYSCTL_NODE(_net, OID_AUTO, ncp, CTLFLAG_RW, NULL, "NetWare requester");
   61 SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, "");
   62 
   63 MODULE_VERSION(ncp, 1);
   64 MODULE_DEPEND(ncp, libmchain, 1, 1, 1);
   65 
   66 static struct cdev *ncp_dev;
   67 
   68 static d_ioctl_t        ncp_ioctl;
   69 
   70 static struct cdevsw ncp_cdevsw = {
   71         .d_version =    D_VERSION,
   72         .d_flags =      D_NEEDGIANT,
   73         .d_ioctl =      ncp_ioctl,
   74         .d_name =       "ncp",
   75 };
   76 
   77 static int ncp_conn_frag_rq(struct ncp_conn *, struct thread *,
   78     struct ncp_conn_frag *);
   79 static int ncp_conn_handler(struct thread *, struct ncpioc_request *,
   80     struct ncp_conn *, struct ncp_handle *);
   81 static int sncp_conn_scan(struct thread *, struct ncpioc_connscan *);
   82 static int sncp_connect(struct thread *, struct ncpioc_connect *);
   83 static int sncp_request(struct thread *, struct ncpioc_request *);
   84 
   85 static int
   86 ncp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
   87 {
   88 
   89         switch (cmd) {
   90         case NCPIOC_CONNECT:
   91                 return (sncp_connect(td, (struct ncpioc_connect *)data));
   92         case NCPIOC_CONNSCAN:
   93                 return (sncp_conn_scan(td, (struct ncpioc_connscan *)data));
   94         case NCPIOC_REQUEST:
   95                 return (sncp_request(td, (struct ncpioc_request *)data));
   96         }
   97         return (EINVAL);
   98 }
   99 
  100 /*
  101  * Attach to NCP server
  102  */
  103 
  104 static int
  105 sncp_connect(struct thread *td, struct ncpioc_connect *args)
  106 {
  107         int connHandle = 0, error;
  108         struct ncp_conn *conn;
  109         struct ncp_handle *handle;
  110         struct ncp_conn_args li;
  111 
  112         checkbad(copyin(args->ioc_li,&li,sizeof(li)));
  113         /* XXX Should be useracc() */
  114         checkbad(copyout(&connHandle,args->ioc_connhandle,
  115             sizeof(connHandle)));
  116         li.password = li.user = NULL;
  117         error = ncp_conn_getattached(&li, td, td->td_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn);
  118         if (error) {
  119                 error = ncp_conn_alloc(&li, td, td->td_ucred, &conn);
  120                 if (error)
  121                         goto bad;
  122                 error = ncp_conn_reconnect(conn);
  123                 if (error)
  124                         ncp_conn_free(conn);
  125         }
  126         if (!error) {
  127                 error = ncp_conn_gethandle(conn, td, &handle);
  128                 copyout(&handle->nh_id, args->ioc_connhandle,
  129                     sizeof(args->ioc_connhandle));
  130                 ncp_conn_unlock(conn,td);
  131         }
  132 bad:
  133         return error;
  134 }
  135 
  136 static int
  137 sncp_request(struct thread *td, struct ncpioc_request *args)
  138 {
  139         struct ncp_rq *rqp;
  140         struct ncp_conn *conn;
  141         struct ncp_handle *handle;
  142         int error = 0, rqsize;
  143 
  144         error = ncp_conn_findhandle(args->ioc_connhandle, td, &handle);
  145         if (error)
  146                 return error;
  147         conn = handle->nh_conn;
  148         if (args->ioc_fn == NCP_CONN)
  149                 return ncp_conn_handler(td, args, conn, handle);
  150         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  151         if (error)
  152                 return(error);
  153         error = ncp_rq_alloc(args->ioc_fn, conn, td, td->td_ucred, &rqp);
  154         if (error)
  155                 return error;
  156         if (rqsize) {
  157                 error = mb_put_mem(&rqp->rq, (caddr_t)args->ioc_ncpbuf->packet,
  158                     rqsize, MB_MUSER);
  159                 if (error)
  160                         goto bad;
  161         }
  162         rqp->nr_flags |= NCPR_DONTFREEONERR;
  163         error = ncp_request(rqp);
  164         if (error == 0 && rqp->nr_rpsize)
  165                 error = md_get_mem(&rqp->rp, (caddr_t)args->ioc_ncpbuf->packet, 
  166                                 rqp->nr_rpsize, MB_MUSER);
  167         copyout(&rqp->nr_cs, &args->ioc_ncpbuf->cs, sizeof(rqp->nr_cs));
  168         copyout(&rqp->nr_cc, &args->ioc_ncpbuf->cc, sizeof(rqp->nr_cc));
  169         copyout(&rqp->nr_rpsize, &args->ioc_ncpbuf->rpsize, sizeof(rqp->nr_rpsize));
  170 bad:
  171         ncp_rq_done(rqp);
  172         return error;
  173 }
  174 
  175 static int
  176 ncp_mod_login(struct ncp_conn *conn, char *user, int objtype, char *password,
  177         struct thread *td, struct ucred *cred)
  178 {
  179         int error;
  180 
  181         if (ncp_suser(cred) != 0 && cred->cr_uid != conn->nc_owner->cr_uid)
  182                 return EACCES;
  183         conn->li.user = ncp_str_dup(user);
  184         if (conn->li.user == NULL)
  185                 return ENOMEM;
  186         conn->li.password = ncp_str_dup(password);
  187         if (conn->li.password == NULL) {
  188                 error = ENOMEM;
  189                 goto bad;
  190         }
  191         ncp_str_upper(conn->li.user);
  192         if ((conn->li.opt & NCP_OPT_NOUPCASEPASS) == 0)
  193                 ncp_str_upper(conn->li.password);
  194         conn->li.objtype = objtype;
  195         error = ncp_conn_login(conn, td, cred);
  196         return error;
  197 bad:
  198         if (conn->li.user) {
  199                 free(conn->li.user, M_NCPDATA);
  200                 conn->li.user = NULL;
  201         }
  202         if (conn->li.password) {
  203                 free(conn->li.password, M_NCPDATA);
  204                 conn->li.password = NULL;
  205         }
  206         return error;
  207 }
  208 
  209 static int
  210 ncp_conn_handler(struct thread *td, struct ncpioc_request *args,
  211         struct ncp_conn *conn, struct ncp_handle *hp)
  212 {
  213         int error = 0, rqsize, subfn;
  214         struct ucred *cred;
  215 
  216         char *pdata;
  217 
  218         cred = td->td_ucred;
  219         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  220         if (error)
  221                 return(error);
  222         error = 0;
  223         pdata = args->ioc_ncpbuf->packet;
  224         subfn = *(pdata++) & 0xff;
  225         rqsize--;
  226         switch (subfn) {
  227             case NCP_CONN_READ: case NCP_CONN_WRITE: {
  228                 struct ncp_rw rwrq;
  229                 struct uio auio;
  230                 struct iovec iov;
  231 
  232                 if (rqsize != sizeof(rwrq))
  233                         return (EBADRPC);
  234                 error = copyin(pdata,&rwrq,rqsize);
  235                 if (error)
  236                         return (error);
  237                 iov.iov_base = rwrq.nrw_base;
  238                 iov.iov_len = rwrq.nrw_cnt;
  239                 auio.uio_iov = &iov;
  240                 auio.uio_iovcnt = 1;
  241                 auio.uio_offset = rwrq.nrw_offset;
  242                 auio.uio_resid = rwrq.nrw_cnt;
  243                 auio.uio_segflg = UIO_USERSPACE;
  244                 auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE;
  245                 auio.uio_td = td;
  246                 if (subfn == NCP_CONN_READ)
  247                         error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred);
  248                 else
  249                         error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred);
  250                 rwrq.nrw_cnt -= auio.uio_resid;
  251                 /*td->td_retval[0] = rwrq.nrw_cnt;*/
  252                 break;
  253             } /* case int_read/write */
  254             case NCP_CONN_SETFLAGS: {
  255                 u_int16_t mask, flags;
  256 
  257                 error = copyin(pdata,&mask, sizeof(mask));
  258                 if (error)
  259                         return error;
  260                 pdata += sizeof(mask);
  261                 error = copyin(pdata,&flags,sizeof(flags));
  262                 if (error)
  263                         return error;
  264                 error = ncp_conn_lock(conn, td, cred, NCPM_WRITE);
  265                 if (error)
  266                         return error;
  267                 if (mask & NCPFL_PERMANENT) {
  268                         conn->flags &= ~NCPFL_PERMANENT;
  269                         conn->flags |= (flags & NCPFL_PERMANENT);
  270                 }
  271                 if (mask & NCPFL_PRIMARY) {
  272                         error = ncp_conn_setprimary(conn, flags & NCPFL_PRIMARY);
  273                         if (error) {
  274                                 ncp_conn_unlock(conn, td);
  275                                 break;
  276                         }
  277                 }
  278                 ncp_conn_unlock(conn, td);
  279                 break;
  280             }
  281             case NCP_CONN_LOGIN: {
  282                 struct ncp_conn_login la;
  283 
  284                 if (rqsize != sizeof(la))
  285                         return EBADRPC;
  286                 if (conn->flags & NCPFL_LOGGED)
  287                         return EALREADY;
  288                 if ((error = copyin(pdata,&la,rqsize)) != 0)
  289                         break;
  290                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE | NCPM_WRITE);
  291                 if (error)
  292                         return error;
  293                 error = ncp_mod_login(conn, la.username, la.objtype,
  294                     la.password, td, td->td_ucred);
  295                 ncp_conn_unlock(conn, td);
  296                 break;
  297             }
  298             case NCP_CONN_GETINFO: {
  299                 struct ncp_conn_stat ncs;
  300                 int len = sizeof(ncs);
  301 
  302                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  303                 if (error)
  304                         return error;
  305                 ncp_conn_getinfo(conn, &ncs);
  306                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  307                 error = copyout(&ncs, &args->ioc_ncpbuf->packet, len);
  308                 ncp_conn_unlock(conn, td);
  309                 break;
  310             }
  311             case NCP_CONN_GETUSER: {
  312                 int len;
  313 
  314                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  315                 if (error)
  316                         return error;
  317                 len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0;
  318                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  319                 if (len) {
  320                         error = copyout(conn->li.user,
  321                             &args->ioc_ncpbuf->packet, len);
  322                 }
  323                 ncp_conn_unlock(conn, td);
  324                 break;
  325             }
  326             case NCP_CONN_CONN2REF: {
  327                 int len = sizeof(int);
  328 
  329                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  330                 if (error)
  331                         return error;
  332                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  333                 if (len) {
  334                         error = copyout(&conn->nc_id,
  335                             &args->ioc_ncpbuf->packet, len);
  336                 }
  337                 ncp_conn_unlock(conn, td);
  338                 break;
  339             }
  340             case NCP_CONN_FRAG: {
  341                 struct ncp_conn_frag nf;
  342 
  343                 if (rqsize != sizeof(nf))
  344                         return (EBADRPC);
  345                 if ((error = copyin(pdata, &nf, rqsize)) != 0) break;
  346                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  347                 if (error)
  348                         return error;
  349                 error = ncp_conn_frag_rq(conn, td, &nf);
  350                 ncp_conn_unlock(conn, td);
  351                 copyout(&nf, &pdata, sizeof(nf));
  352                 td->td_retval[0] = error;
  353                 break;
  354             }
  355             case NCP_CONN_DUP: {
  356                 struct ncp_handle *newhp;
  357                 int len = sizeof(NWCONN_HANDLE);
  358 
  359                 error = ncp_conn_lock(conn, td, cred, NCPM_READ);
  360                 if (error) break;
  361                 copyout(&len, &args->ioc_ncpbuf->rpsize, len);
  362                 error = ncp_conn_gethandle(conn, td, &newhp);
  363                 if (!error)
  364                         error = copyout(&newhp->nh_id,
  365                             args->ioc_ncpbuf->packet, len);
  366                 ncp_conn_unlock(conn, td);
  367                 break;
  368             }
  369             case NCP_CONN_CONNCLOSE: {
  370                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  371                 if (error) break;
  372                 ncp_conn_puthandle(hp, td, 0);
  373                 error = ncp_conn_free(conn);
  374                 if (error)
  375                         ncp_conn_unlock(conn, td);
  376                 break;
  377             }
  378             default:
  379                     error = EOPNOTSUPP;
  380         }
  381         return error;
  382 }
  383 
  384 static int
  385 sncp_conn_scan(struct thread *td, struct ncpioc_connscan *args)
  386 {
  387         int connHandle = 0, error;
  388         struct ncp_conn_args li, *lip;
  389         struct ncp_conn *conn;
  390         struct ncp_handle *hp;
  391         char *user = NULL, *password = NULL;
  392 
  393         if (args->ioc_li) {
  394                 if (copyin(args->ioc_li, &li, sizeof(li)))
  395                         return EFAULT;
  396                 lip = &li;
  397         } else {
  398                 lip = NULL;
  399         }
  400 
  401         if (lip != NULL) {
  402                 lip->server[sizeof(lip->server)-1]=0; /* just to make sure */
  403                 ncp_str_upper(lip->server);
  404                 if (lip->user) {
  405                         user = ncp_str_dup(lip->user);
  406                         if (user == NULL)
  407                                 return EINVAL;
  408                         ncp_str_upper(user);
  409                 }
  410                 if (lip->password) {
  411                         password = ncp_str_dup(lip->password);
  412                         if (password == NULL) {
  413                                 if (user)
  414                                         free(user, M_NCPDATA);
  415                                 return EINVAL;
  416                         }
  417                         ncp_str_upper(password);
  418                 }
  419                 lip->user = user;
  420                 lip->password = password;
  421         }
  422         error = ncp_conn_getbyli(lip, td, td->td_ucred, NCPM_EXECUTE, &conn);
  423         if (!error) {           /* already have this login */
  424                 ncp_conn_gethandle(conn, td, &hp);
  425                 connHandle = hp->nh_id;
  426                 ncp_conn_unlock(conn, td);
  427                 copyout(&connHandle, args->ioc_connhandle, sizeof(connHandle));
  428         }
  429         if (user)
  430                 free(user, M_NCPDATA);
  431         if (password)
  432                 free(password, M_NCPDATA);
  433         return error;
  434 
  435 }
  436 
  437 int
  438 ncp_conn_frag_rq(struct ncp_conn *conn, struct thread *td,
  439                  struct ncp_conn_frag *nfp)
  440 {
  441         NW_FRAGMENT *fp;
  442         struct ncp_rq *rqp;
  443         u_int32_t fsize;
  444         int error, i, rpsize;
  445 
  446         error = ncp_rq_alloc(nfp->fn, conn, td, td->td_ucred, &rqp);
  447         if (error)
  448                 return error;
  449         for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
  450                 error = mb_put_mem(&rqp->rq, (caddr_t)fp->fragAddress, fp->fragSize, MB_MUSER);
  451                 if (error)
  452                         goto bad;
  453         }
  454         rqp->nr_flags |= NCPR_DONTFREEONERR;
  455         error = ncp_request(rqp);
  456         if (error)
  457                 goto bad;
  458         rpsize = rqp->nr_rpsize;
  459         if (rpsize && nfp->rpfcnt) {
  460                 for(fp = nfp->rpf, i = 0; i < nfp->rpfcnt; i++, fp++) {
  461                         error = copyin(&fp->fragSize, &fsize, sizeof (fsize));
  462                         if (error)
  463                                 break;
  464                         fsize = min(fsize, rpsize);
  465                         error = md_get_mem(&rqp->rp, (caddr_t)fp->fragAddress, fsize, MB_MUSER);
  466                         if (error)
  467                                 break;
  468                         rpsize -= fsize;
  469                         error = copyout(&fsize, &fp->fragSize, sizeof (fsize));
  470                         if (error)
  471                                 break;
  472                 }
  473         }
  474         nfp->cs = rqp->nr_cs;
  475         nfp->cc = rqp->nr_cc;
  476 bad:
  477         ncp_rq_done(rqp);
  478         return error;
  479 }
  480 
  481 static int
  482 ncp_load(void)
  483 {
  484         int error;
  485 
  486         if ((error = ncp_init()) != 0)
  487                 return (error);
  488         ncp_dev = make_dev(&ncp_cdevsw, 0, 0, 0, 0666, "ncp");
  489         printf("ncp_load: loaded\n");
  490         return (0);
  491 }
  492 
  493 static int
  494 ncp_unload(void)
  495 {
  496         int error;
  497 
  498         error = ncp_done();
  499         if (error)
  500                 return (error);
  501         destroy_dev(ncp_dev);
  502         printf("ncp_unload: unloaded\n");
  503         return (0);
  504 }
  505 
  506 static int
  507 ncp_mod_handler(module_t mod, int type, void *data)
  508 {
  509         int error;
  510 
  511         switch (type) {
  512         case MOD_LOAD:
  513                 error = ncp_load();
  514                 break;
  515         case MOD_UNLOAD:
  516                 error = ncp_unload();
  517                 break;
  518         default:
  519                 error = EINVAL;
  520         }
  521         return error;
  522 }
  523 
  524 static moduledata_t ncp_mod = {
  525         "ncp",
  526         ncp_mod_handler,
  527         NULL
  528 };
  529 DECLARE_MODULE(ncp, ncp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);

Cache object: 74b72f74dd41e8cac339eb78cfb00c7b


[ 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.