Print this page
    
10120 smatch indenting fixes for usr/src/cmd
Reviewed by: Gergő Doma <domag02@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/cmd-inet/common/kcmd.c
          +++ new/usr/src/cmd/cmd-inet/common/kcmd.c
   1    1  /*
   2    2   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
   3    3   * Use is subject to license terms.
   4    4   */
   5    5  
   6    6  /*
   7    7   * Copyright (c) 1983 Regents of the University of California.
   8    8   * All rights reserved.
   9    9   *
  10   10   * Redistribution and use in source and binary forms are permitted
  11   11   * provided that the above copyright notice and this paragraph are
  12   12   * duplicated in all such forms and that any documentation,
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * advertising materials, and other materials related to such
  14   14   * distribution and use acknowledge that the software was developed
  15   15   * by the University of California, Berkeley.  The name of the
  16   16   * University may not be used to endorse or promote products derived
  17   17   * from this software without specific prior written permission.
  18   18   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19   19   * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20   20   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21   21   */
  22   22  
       23 +/*
       24 + * Copyright (c) 2018, Joyent, Inc.
       25 + */
       26 +
  23   27  /* derived from @(#)rcmd.c      5.17 (Berkeley) 6/27/88 */
  24   28  
  25   29  #include <unistd.h>
  26   30  #include <stdlib.h>
  27   31  #include <stdio.h>
  28   32  #include <ctype.h>
  29   33  #include <string.h>
  30   34  #include <pwd.h>
  31   35  #include <sys/param.h>
  32   36  #include <sys/types.h>
  33   37  #include <fcntl.h>
  34   38  
  35   39  #include <signal.h>
  36   40  #include <sys/file.h>
  37   41  #include <sys/socket.h>
  38   42  #include <sys/stat.h>
  39   43  
  40   44  #include <netinet/in.h>
  41   45  #include <arpa/inet.h>
  42   46  #include <netdb.h>
  43   47  #include <locale.h>
  44   48  #include <syslog.h>
  45   49  
  46   50  #include <errno.h>
  47   51  #include <com_err.h>
  48   52  #include <k5-int.h>
  49   53  #include <kcmd.h>
  50   54  
  51   55  static char *default_service = "host";
  52   56  
  53   57  #define KCMD_BUFSIZ     102400
  54   58  #define KCMD8_BUFSIZ    (4096 - 256)
  55   59  /*
  56   60   * For compatibility with earlier versions of Solaris and other OS
  57   61   * (kerborized rsh uses 4KB of RSH_BUFSIZE)- 256 to make sure
  58   62   * there is room
  59   63   */
  60   64  static int deswrite_compat(int, char *, int, int);
  61   65  
  62   66  #define KCMD_KEYUSAGE   1026
  63   67  
  64   68  static char storage[KCMD_BUFSIZ];
  65   69  static int nstored = 0;
  66   70  static int MAXSIZE = (KCMD_BUFSIZ + 8);
  67   71  static char *store_ptr = storage;
  68   72  static krb5_data desinbuf, desoutbuf;
  69   73  
  70   74  static boolean_t encrypt_flag = B_FALSE;
  71   75  static krb5_context kcmd_context;
  72   76  
  73   77  /* XXX Overloaded: use_ivecs!=0 -> new protocol, inband signalling, etc.  */
  74   78  static boolean_t use_ivecs = B_FALSE;
  75   79  static krb5_data encivec_i[2], encivec_o[2];
  76   80  static krb5_keyusage enc_keyusage_i[2], enc_keyusage_o[2];
  77   81  static krb5_enctype final_enctype;
  78   82  static krb5_keyblock *skey;
  79   83  
  80   84  /* ARGSUSED */
  81   85  int
  82   86  kcmd(int *sock, char **ahost, ushort_t rport,
  83   87          char *locuser, char *remuser,
  84   88          char *cmd, int *fd2p, char *service, char *realm,
  85   89          krb5_context bsd_context, krb5_auth_context *authconp,
  86   90          krb5_creds **cred, krb5_int32 *seqno, krb5_int32 *server_seqno,
  87   91          krb5_flags authopts,
  88   92          int anyport, enum kcmd_proto *protonump)
  89   93  {
  90   94          int s = -1;
  91   95          sigset_t oldmask, urgmask;
  92   96          struct sockaddr_in sin;
  93   97          struct sockaddr_storage from;
  94   98          krb5_creds *get_cred = NULL;
  95   99          krb5_creds *ret_cred = NULL;
  96  100          char c;
  97  101          struct hostent *hp;
  98  102          int rc;
  99  103          char *host_save = NULL;
 100  104          krb5_error_code status;
 101  105          krb5_ap_rep_enc_part *rep_ret;
 102  106          krb5_error      *error = 0;
 103  107          krb5_ccache cc;
 104  108          krb5_data outbuf;
 105  109          krb5_flags options = authopts;
 106  110          krb5_auth_context auth_context = NULL;
 107  111          char *cksumbuf;
 108  112          krb5_data cksumdat;
 109  113          int bsize = 0;
 110  114          char *kcmd_version;
 111  115          enum kcmd_proto protonum = *protonump;
 112  116  
 113  117          bsize = strlen(cmd) + strlen(remuser) + 64;
 114  118          if ((cksumbuf = malloc(bsize)) == 0) {
 115  119                  (void) fprintf(stderr, gettext("Unable to allocate"
 116  120                                              " memory for checksum buffer.\n"));
 117  121                  return (-1);
 118  122          }
 119  123          (void) snprintf(cksumbuf, bsize, "%u:", ntohs(rport));
 120  124          if (strlcat(cksumbuf, cmd, bsize) >= bsize) {
 121  125                  (void) fprintf(stderr, gettext("cmd buffer too long.\n"));
 122  126                  free(cksumbuf);
 123  127                  return (-1);
 124  128          }
 125  129          if (strlcat(cksumbuf, remuser, bsize) >= bsize) {
 126  130                  (void) fprintf(stderr, gettext("remuser too long.\n"));
 127  131                  free(cksumbuf);
 128  132                  return (-1);
 129  133          }
 130  134          cksumdat.data = cksumbuf;
 131  135          cksumdat.length = strlen(cksumbuf);
 132  136  
 133  137          hp = gethostbyname(*ahost);
 134  138          if (hp == 0) {
 135  139                  (void) fprintf(stderr,
 136  140                              gettext("%s: unknown host\n"), *ahost);
 137  141                  return (-1);
 138  142          }
 139  143  
 140  144          if ((host_save = (char *)strdup(hp->h_name)) == NULL) {
 141  145                  (void) fprintf(stderr, gettext("kcmd: no memory\n"));
 142  146                  return (-1);
 143  147          }
 144  148  
 145  149          /* If no service is given set to the default service */
 146  150          if (!service) service = default_service;
 147  151  
 148  152          if (!(get_cred = (krb5_creds *)calloc(1, sizeof (krb5_creds)))) {
 149  153                  (void) fprintf(stderr, gettext("kcmd: no memory\n"));
 150  154                  return (-1);
 151  155          }
 152  156          (void) sigemptyset(&urgmask);
 153  157          (void) sigaddset(&urgmask, SIGURG);
 154  158          (void) sigprocmask(SIG_BLOCK, &urgmask, &oldmask);
 155  159  
 156  160          status = krb5_sname_to_principal(bsd_context, host_save, service,
 157  161                                          KRB5_NT_SRV_HST, &get_cred->server);
 158  162          if (status) {
 159  163                  (void) fprintf(stderr,
 160  164                              gettext("kcmd: "
 161  165                                      "krb5_sname_to_principal failed: %s\n"),
 162  166                              error_message(status));
 163  167                  status = -1;
 164  168                  goto bad;
 165  169          }
 166  170  
 167  171          if (realm && *realm) {
 168  172                  (void) krb5_xfree(
 169  173                          krb5_princ_realm(bsd_context, get_cred->server)->data);
 170  174                  krb5_princ_set_realm_length(bsd_context, get_cred->server,
 171  175                                          strlen(realm));
 172  176                  krb5_princ_set_realm_data(bsd_context, get_cred->server,
 173  177                                                  strdup(realm));
 174  178          }
 175  179  
 176  180          s = socket(AF_INET, SOCK_STREAM, 0);
 177  181          if (s < 0) {
 178  182                  perror(gettext("Error creating socket"));
 179  183                  status = -1;
 180  184                  goto bad;
 181  185          }
 182  186          /*
 183  187           * Kerberos only supports IPv4 addresses for now.
 184  188           */
 185  189          if (hp->h_addrtype == AF_INET) {
 186  190                  sin.sin_family = hp->h_addrtype;
 187  191                  (void) memcpy((void *)&sin.sin_addr,
 188  192                              hp->h_addr, hp->h_length);
 189  193                  sin.sin_port = rport;
 190  194          } else {
 191  195                  syslog(LOG_ERR, "Address type %d not supported for "
 192  196                      "Kerberos", hp->h_addrtype);
 193  197                  status = -1;
 194  198                  goto bad;
 195  199          }
 196  200  
 197  201          if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
 198  202                  perror(host_save);
 199  203                  status = -1;
 200  204                  goto bad;
 201  205          }
 202  206  
 203  207          if (fd2p == 0) {
 204  208                  (void) write(s, "", 1);
 205  209          } else {
 206  210                  char num[16];
 207  211                  int s2;
 208  212                  int s3;
 209  213                  struct sockaddr_storage sname;
 210  214                  struct sockaddr_in *sp;
 211  215                  int len = sizeof (struct sockaddr_storage);
 212  216  
 213  217                  s2 = socket(AF_INET, SOCK_STREAM, 0);
 214  218                  if (s2 < 0) {
 215  219                          status = -1;
 216  220                          goto bad;
 217  221                  }
 218  222                  (void) memset((char *)&sin, 0, sizeof (sin));
 219  223                  sin.sin_family = AF_INET;
 220  224                  sin.sin_addr.s_addr = INADDR_ANY;
 221  225                  sin.sin_port = 0;
 222  226  
 223  227                  if (bind(s2, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
 224  228                          perror(gettext("error binding socket"));
 225  229                          (void) close(s2);
 226  230                          status = -1;
 227  231                          goto bad;
 228  232                  }
 229  233                  if (getsockname(s2, (struct sockaddr *)&sname, &len) < 0) {
 230  234                          perror(gettext("getsockname error"));
 231  235                          (void) close(s2);
 232  236                          status = -1;
 233  237                          goto bad;
 234  238                  }
 235  239                  sp = (struct sockaddr_in *)&sname;
 236  240                  (void) listen(s2, 1);
 237  241                  (void) snprintf(num, sizeof (num), "%d",
 238  242                              htons((ushort_t)sp->sin_port));
 239  243                  if (write(s, num, strlen(num)+1) != strlen(num)+1) {
 240  244                          perror(gettext("write: error setting up stderr"));
 241  245                          (void) close(s2);
 242  246                          status = -1;
 243  247                          goto bad;
 244  248                  }
 245  249  
 246  250                  s3 = accept(s2, (struct sockaddr *)&from, &len);
 247  251                  (void) close(s2);
 248  252                  if (s3 < 0) {
 249  253                          perror(gettext("accept"));
 250  254                          status = -1;
 251  255                          goto bad;
 252  256                  }
 253  257                  *fd2p = s3;
 254  258                  if (SOCK_FAMILY(from) == AF_INET) {
 255  259                          if (!anyport && SOCK_PORT(from) >= IPPORT_RESERVED) {
 256  260                                  (void) fprintf(stderr,
 257  261                                      gettext("socket: protocol "
 258  262                                              "failure in circuit setup.\n"));
 259  263                                  status = -1;
 260  264                                  goto bad2;
 261  265                          }
 262  266                  } else {
 263  267                          (void) fprintf(stderr,
 264  268                                      gettext("Kerberos does not support "
 265  269                                              "address type %d\n"),
 266  270                                      SOCK_FAMILY(from));
 267  271                          status = -1;
 268  272                          goto bad2;
 269  273                  }
 270  274          }
 271  275  
 272  276          if (status = krb5_cc_default(bsd_context, &cc))
 273  277                  goto bad2;
 274  278  
 275  279          status = krb5_cc_get_principal(bsd_context, cc, &get_cred->client);
 276  280          if (status) {
 277  281                  (void) krb5_cc_close(bsd_context, cc);
 278  282                  goto bad2;
 279  283          }
 280  284  
 281  285          /* Get ticket from credentials cache or kdc */
 282  286          status = krb5_get_credentials(bsd_context, 0, cc, get_cred, &ret_cred);
 283  287          (void) krb5_cc_close(bsd_context, cc);
 284  288          if (status) goto bad2;
 285  289  
 286  290          /* Reset internal flags; these should not be sent. */
 287  291          authopts &= (~OPTS_FORWARD_CREDS);
 288  292          authopts &= (~OPTS_FORWARDABLE_CREDS);
 289  293  
 290  294          if ((status = krb5_auth_con_init(bsd_context, &auth_context)))
 291  295                  goto bad2;
 292  296  
 293  297          if ((status = krb5_auth_con_setflags(bsd_context, auth_context,
 294  298                                          KRB5_AUTH_CONTEXT_RET_TIME)))
 295  299                  goto bad2;
 296  300  
 297  301          /* Only need local address for mk_cred() to send to krlogind */
 298  302          if ((status = krb5_auth_con_genaddrs(bsd_context, auth_context, s,
 299  303                          KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
 300  304                  goto bad2;
 301  305  
 302  306          if (protonum == KCMD_PROTOCOL_COMPAT_HACK) {
 303  307                  krb5_boolean is_des;
 304  308                  status = krb5_c_enctype_compare(bsd_context,
 305  309                                                  ENCTYPE_DES_CBC_CRC,
 306  310                                                  ret_cred->keyblock.enctype,
 307  311                                                  &is_des);
 308  312                  if (status)
 309  313                          goto bad2;
 310  314                  protonum = is_des ? KCMD_OLD_PROTOCOL : KCMD_NEW_PROTOCOL;
 311  315          }
 312  316  
 313  317          switch (protonum) {
 314  318          case KCMD_NEW_PROTOCOL:
 315  319                  authopts |= AP_OPTS_USE_SUBKEY;
 316  320                  kcmd_version = "KCMDV0.2";
 317  321                  break;
 318  322          case KCMD_OLD_PROTOCOL:
 319  323                  kcmd_version = "KCMDV0.1";
 320  324                  break;
 321  325          default:
 322  326                  status = -1;
 323  327                  goto bad2;
 324  328          }
 325  329  
 326  330          /*
 327  331           * Call the Kerberos library routine to obtain an authenticator,
 328  332           * pass it over the socket to the server, and obtain mutual
 329  333           * authentication.
 330  334           */
 331  335          status = krb5_sendauth(bsd_context, &auth_context, (krb5_pointer) &s,
 332  336                          kcmd_version, ret_cred->client, ret_cred->server,
 333  337                          authopts, &cksumdat, ret_cred, 0, &error,
 334  338                          &rep_ret, NULL);
 335  339          krb5_xfree(cksumdat.data);
 336  340          if (status) {
 337  341                  (void) fprintf(stderr, gettext("Couldn't authenticate"
 338  342                                              " to server: %s\n"),
 339  343                              error_message(status));
 340  344                  if (error) {
 341  345                          (void) fprintf(stderr, gettext("Server returned error"
 342  346                                                  " code %d (%s)\n"),
 343  347                                  error->error,
 344  348                                  error_message(ERROR_TABLE_BASE_krb5 +
 345  349                                              error->error));
 346  350                          if (error->text.length)
 347  351                                  (void) fprintf(stderr,
 348  352                                              gettext("Error text"
 349  353                                                      " sent from server: %s\n"),
 350  354                                              error->text.data);
 351  355                  }
 352  356                  if (error) {
 353  357                          krb5_free_error(bsd_context, error);
 354  358                          error = 0;
 355  359                  }
 356  360                  goto bad2;
 357  361          }
 358  362          if (rep_ret && server_seqno) {
 359  363                  *server_seqno = rep_ret->seq_number;
 360  364                  krb5_free_ap_rep_enc_part(bsd_context, rep_ret);
 361  365          }
 362  366  
 363  367          (void) write(s, remuser, strlen(remuser)+1);
 364  368          (void) write(s, cmd, strlen(cmd)+1);
 365  369          if (locuser)
 366  370                  (void) write(s, locuser, strlen(locuser)+1);
 367  371          else
 368  372                  (void) write(s, "", 1);
 369  373  
 370  374          if (options & OPTS_FORWARD_CREDS) {   /* Forward credentials */
 371  375                  if (status = krb5_fwd_tgt_creds(bsd_context, auth_context,
 372  376                                          host_save,
 373  377                                          ret_cred->client, ret_cred->server,
 374  378                                          0, options & OPTS_FORWARDABLE_CREDS,
 375  379                                          &outbuf)) {
 376  380                          (void) fprintf(stderr,
 377  381                                      gettext("kcmd: Error getting"
 378  382                                              " forwarded creds\n"));
 379  383                          goto bad2;
 380  384                  }
 381  385                  /* Send forwarded credentials */
 382  386                  if (status = krb5_write_message(bsd_context, (krb5_pointer)&s,
 383  387                                                  &outbuf))
 384  388                          goto bad2;
 385  389          } else { /* Dummy write to signal no forwarding */
 386  390                  outbuf.length = 0;
 387  391                  if (status = krb5_write_message(bsd_context,
 388  392                                                  (krb5_pointer)&s, &outbuf))
 389  393                          goto bad2;
 390  394          }
 391  395  
 392  396          if ((rc = read(s, &c, 1)) != 1) {
 393  397                  if (rc == -1) {
 394  398                          perror(*ahost);
 395  399                  } else {
 396  400                          (void) fprintf(stderr, gettext("kcmd: bad connection "
 397  401                                          "with remote host\n"));
 398  402                  }
 399  403                  status = -1;
 400  404                  goto bad2;
 401  405          }
 402  406          if (c != 0) {
 403  407                  while (read(s, &c, 1) == 1) {
 404  408                          (void) write(2, &c, 1);
  
    | 
      ↓ open down ↓ | 
    372 lines elided | 
    
      ↑ open up ↑ | 
  
 405  409                          if (c == '\n')
 406  410                                  break;
 407  411                  }
 408  412                  status = -1;
 409  413                  goto bad2;
 410  414          }
 411  415          (void) sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0);
 412  416          *sock = s;
 413  417  
 414  418          /* pass back credentials if wanted */
 415      -        if (cred) (void) krb5_copy_creds(bsd_context, ret_cred, cred);
 416      -                krb5_free_creds(bsd_context, ret_cred);
      419 +        if (cred)
      420 +                (void) krb5_copy_creds(bsd_context, ret_cred, cred);
      421 +
      422 +        krb5_free_creds(bsd_context, ret_cred);
      423 +
 417  424          /*
 418  425           * Initialize *authconp to auth_context, so
 419  426           * that the clients can make use of it
 420  427           */
 421  428          *authconp = auth_context;
 422  429  
 423  430          return (0);
 424  431  bad2:
 425  432          if (fd2p != NULL)
 426  433                  (void) close(*fd2p);
 427  434  bad:
 428  435          if (s > 0)
 429  436                  (void) close(s);
 430  437          if (get_cred)
 431  438                  krb5_free_creds(bsd_context, get_cred);
 432  439          if (ret_cred)
 433  440                  krb5_free_creds(bsd_context, ret_cred);
 434  441          if (host_save)
 435  442                  free(host_save);
 436  443          (void) sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0);
 437  444          return (status);
 438  445  }
 439  446  
 440  447  /*
 441  448   * Strsave was a routine in the version 4 krb library: we put it here
 442  449   * for compatablilty with version 5 krb library, since kcmd.o is linked
 443  450   * into all programs.
 444  451   */
 445  452  
 446  453  char *
 447  454  strsave(char *sp)
 448  455  {
 449  456          char *ret;
 450  457  
 451  458          if ((ret = (char *)strdup(sp)) == NULL) {
 452  459                  (void) fprintf(stderr, gettext("no memory for saving args\n"));
 453  460                  exit(1);
 454  461          }
 455  462          return (ret);
 456  463  }
 457  464  
 458  465  
 459  466  /*
 460  467   * This routine is to initialize the desinbuf, desoutbuf and the session key
 461  468   * structures to carry out desread()'s and deswrite()'s successfully
 462  469   */
 463  470  void
 464  471  init_encrypt(int enc, krb5_context ctxt, enum kcmd_proto protonum,
 465  472          krb5_data *inbuf, krb5_data *outbuf,
 466  473          int amclient, krb5_encrypt_block *block)
 467  474  {
 468  475          krb5_error_code statuscode;
 469  476          size_t blocksize;
 470  477          int i;
 471  478          krb5_error_code ret;
 472  479  
 473  480          kcmd_context = ctxt;
 474  481  
 475  482          if (enc > 0) {
 476  483                  desinbuf.data = inbuf->data;
 477  484                  desoutbuf.data = outbuf->data + 4;
 478  485                  desinbuf.length = inbuf->length;
 479  486                  desoutbuf.length = outbuf->length + 4;
 480  487                  encrypt_flag = B_TRUE;
 481  488          } else {
 482  489                  encrypt_flag = B_FALSE;
 483  490                  return;
 484  491          }
 485  492  
 486  493          skey = block->key;
 487  494          final_enctype = skey->enctype;
 488  495  
 489  496          enc_keyusage_i[0] = KCMD_KEYUSAGE;
 490  497          enc_keyusage_i[1] = KCMD_KEYUSAGE;
 491  498          enc_keyusage_o[0] = KCMD_KEYUSAGE;
 492  499          enc_keyusage_o[1] = KCMD_KEYUSAGE;
 493  500  
 494  501          if (protonum == KCMD_OLD_PROTOCOL) {
 495  502                  use_ivecs = B_FALSE;
 496  503                  return;
 497  504          }
 498  505  
 499  506          use_ivecs = B_TRUE;
 500  507          switch (skey->enctype) {
 501  508          /*
 502  509           * For the DES-based enctypes and the 3DES enctype we
 503  510           * want to use a non-zero  IV because that's what we did.
 504  511           * In the future we use different keyusage for each
 505  512           * channel and direction and a fresh cipher state.
 506  513           */
 507  514          case ENCTYPE_DES_CBC_CRC:
 508  515          case ENCTYPE_DES_CBC_MD4:
 509  516          case ENCTYPE_DES_CBC_MD5:
 510  517          case ENCTYPE_DES3_CBC_SHA1:
 511  518                  statuscode = krb5_c_block_size(kcmd_context, final_enctype,
 512  519                                  &blocksize);
 513  520                  if (statuscode) {
 514  521                          /* XXX what do I do? */
 515  522                          abort();
 516  523                  }
 517  524  
 518  525                  encivec_i[0].length = encivec_i[1].length =
 519  526                  encivec_o[0].length = encivec_o[1].length = blocksize;
 520  527  
 521  528                  if ((encivec_i[0].data = malloc(encivec_i[0].length * 4))
 522  529                          == NULL) {
 523  530                          /* XXX what do I do? */
 524  531                          abort();
 525  532                  }
 526  533                  encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
 527  534                  encivec_o[0].data = encivec_i[1].data + encivec_i[0].length;
 528  535                  encivec_o[1].data = encivec_o[0].data + encivec_i[0].length;
 529  536  
 530  537                  /* is there a better way to initialize this? */
 531  538                  (void) memset(encivec_i[0].data, amclient, blocksize);
 532  539                  (void) memset(encivec_o[0].data, 1 - amclient, blocksize);
 533  540                  (void) memset(encivec_i[1].data, 2 | amclient, blocksize);
 534  541                  (void) memset(encivec_o[1].data, 2 | (1 - amclient), blocksize);
 535  542                  break;
 536  543          default:
 537  544                  if (amclient) {
 538  545                          enc_keyusage_i[0] = 1028;
 539  546                          enc_keyusage_i[1] = 1030;
 540  547                          enc_keyusage_o[0] = 1032;
 541  548                          enc_keyusage_o[1] = 1034;
 542  549                  } else { /* amclient */
 543  550                          enc_keyusage_i[0] = 1032;
 544  551                          enc_keyusage_i[1] = 1034;
 545  552                          enc_keyusage_o[0] = 1028;
 546  553                          enc_keyusage_o[1] = 1030;
 547  554                  }
 548  555                  for (i = 0; i < 2; i++) {
 549  556                          ret = krb5_c_init_state(ctxt,
 550  557                                  skey, enc_keyusage_i[i],
 551  558                                  &encivec_i[i]);
 552  559                          if (ret)
 553  560                                  goto fail;
 554  561                          ret = krb5_c_init_state(ctxt,
 555  562                                  skey, enc_keyusage_o[i],
 556  563                                  &encivec_o[i]);
 557  564                          if (ret)
 558  565                                  goto fail;
 559  566                  }
 560  567                  break;
 561  568          }
 562  569          return;
 563  570  fail:
 564  571          abort();
 565  572  }
 566  573  
 567  574  int
 568  575  desread(int fd, char *buf, int len, int secondary)
 569  576  {
 570  577          int nreturned = 0;
 571  578          long net_len, rd_len;
 572  579          int cc;
 573  580          size_t ret = 0;
 574  581          unsigned char len_buf[4];
 575  582          krb5_enc_data inputd;
 576  583          krb5_data outputd;
 577  584  
 578  585          if (!encrypt_flag)
 579  586                  return (read(fd, buf, len));
 580  587  
 581  588          /*
 582  589           * If there is stored data from a previous read,
 583  590           * put it into the output buffer and return it now.
 584  591           */
 585  592          if (nstored >= len) {
 586  593                  (void) memcpy(buf, store_ptr, len);
 587  594                  store_ptr += len;
 588  595                  nstored -= len;
 589  596                  return (len);
 590  597          } else if (nstored) {
 591  598                  (void) memcpy(buf, store_ptr, nstored);
 592  599                  nreturned += nstored;
 593  600                  buf += nstored;
 594  601                  len -= nstored;
 595  602                  nstored = 0;
 596  603          }
 597  604  
 598  605          if ((cc = krb5_net_read(kcmd_context, fd, (char *)len_buf, 4)) != 4) {
 599  606                  if ((cc < 0) && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
 600  607                          return (cc);
 601  608                  /* XXX can't read enough, pipe must have closed */
 602  609                  return (0);
 603  610          }
 604  611          rd_len = ((len_buf[0] << 24) | (len_buf[1] << 16) |
 605  612                      (len_buf[2] << 8) | len_buf[3]);
 606  613  
 607  614          if (krb5_c_encrypt_length(kcmd_context, final_enctype,
 608  615                                  use_ivecs ? (size_t)rd_len + 4 : (size_t)rd_len,
 609  616                                  &ret))
 610  617                  net_len = ((size_t)-1);
 611  618          else
 612  619                  net_len = ret;
 613  620  
 614  621          if ((net_len <= 0) || (net_len > desinbuf.length)) {
 615  622                  /*
 616  623                   * preposterous length; assume out-of-sync; only recourse
 617  624                   * is to close connection, so return 0
 618  625                   */
 619  626                  (void) fprintf(stderr, gettext("Read size problem.\n"));
 620  627                  return (0);
 621  628          }
 622  629  
 623  630          if ((cc = krb5_net_read(kcmd_context, fd, desinbuf.data, net_len))
 624  631              != net_len) {
 625  632                  /* pipe must have closed, return 0 */
 626  633                  (void) fprintf(stderr,
 627  634                              gettext("Read error: length received %d "
 628  635                                      "!= expected %d.\n"),
 629  636                              cc, net_len);
 630  637                  return (0);
 631  638          }
 632  639  
 633  640          /*
 634  641           * Decrypt information
 635  642           */
 636  643          inputd.enctype = ENCTYPE_UNKNOWN;
 637  644          inputd.ciphertext.length = net_len;
 638  645          inputd.ciphertext.data = (krb5_pointer)desinbuf.data;
 639  646  
 640  647          outputd.length = sizeof (storage);
 641  648          outputd.data = (krb5_pointer)storage;
 642  649  
 643  650          /*
 644  651           * data is decrypted into the "storage" buffer, which
 645  652           * had better be large enough!
 646  653           */
 647  654          cc = krb5_c_decrypt(kcmd_context, skey,
 648  655                                  enc_keyusage_i[secondary],
 649  656                                  use_ivecs ? encivec_i + secondary : 0,
 650  657                                  &inputd, &outputd);
 651  658          if (cc) {
 652  659                  (void) fprintf(stderr, gettext("Cannot decrypt data "
 653  660                          "from network\n"));
 654  661                  return (0);
 655  662          }
 656  663  
 657  664          store_ptr = storage;
 658  665          nstored = rd_len;
 659  666          if (use_ivecs == B_TRUE) {
 660  667                  int rd_len2;
 661  668                  rd_len2 = storage[0] & 0xff;
 662  669                  rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
 663  670                  rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
 664  671                  rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
 665  672                  if (rd_len2 != rd_len) {
 666  673                          /* cleartext length trashed? */
 667  674                          errno = EIO;
 668  675                          return (-1);
 669  676                  }
 670  677                  store_ptr += 4;
 671  678          }
 672  679          /*
 673  680           * Copy only as much data as the input buffer will allow.
 674  681           * The rest is kept in the 'storage' pointer for the next
 675  682           * read.
 676  683           */
 677  684          if (nstored > len) {
 678  685                  (void) memcpy(buf, store_ptr, len);
 679  686                  nreturned += len;
 680  687                  store_ptr += len;
 681  688                  nstored -= len;
 682  689          } else {
 683  690                  (void) memcpy(buf, store_ptr, nstored);
 684  691                  nreturned += nstored;
 685  692                  nstored = 0;
 686  693          }
 687  694  
 688  695          return (nreturned);
 689  696  }
 690  697  int
 691  698  deswrite(int fd, char *buf, int len, int secondary)
 692  699  {
 693  700          int bytes_written;
 694  701          int r;
 695  702          int outlen;
 696  703          char *p;
 697  704          if (!encrypt_flag)
 698  705                  return (write(fd, buf, len));
 699  706  
 700  707          bytes_written = 0;
 701  708          while (len > 0) {
 702  709                  p = buf + bytes_written;
 703  710                  if (len > KCMD8_BUFSIZ)
 704  711                          outlen = KCMD8_BUFSIZ;
 705  712                  else
 706  713                          outlen = len;
 707  714                  r = deswrite_compat(fd, p, outlen, secondary);
 708  715                  if (r == -1)
 709  716                          return (r);
 710  717                  bytes_written += r;
 711  718                  len -= r;
 712  719          }
 713  720          return (bytes_written);
 714  721  }
 715  722  static int
 716  723  deswrite_compat(int fd, char *buf, int len, int secondary)
 717  724  {
 718  725          int cc;
 719  726          size_t ret = 0;
 720  727          krb5_data inputd;
 721  728          krb5_enc_data outputd;
 722  729          char tmpbuf[KCMD_BUFSIZ + 8];
 723  730          char encrbuf[KCMD_BUFSIZ + 8];
 724  731          unsigned char *len_buf = (unsigned char *)tmpbuf;
 725  732  
 726  733          if (use_ivecs == B_TRUE) {
 727  734                  unsigned char *lenbuf2 = (unsigned char *)tmpbuf;
 728  735                  if (len + 4 > sizeof (tmpbuf))
 729  736                          abort();
 730  737                  lenbuf2[0] = (len & 0xff000000) >> 24;
 731  738                  lenbuf2[1] = (len & 0xff0000) >> 16;
 732  739                  lenbuf2[2] = (len & 0xff00) >> 8;
 733  740                  lenbuf2[3] = (len & 0xff);
 734  741                  (void) memcpy(tmpbuf + 4, buf, len);
 735  742  
 736  743                  inputd.data = (krb5_pointer)tmpbuf;
 737  744                  inputd.length = len + 4;
 738  745          } else {
 739  746                  inputd.data = (krb5_pointer)buf;
 740  747                  inputd.length = len;
 741  748          }
 742  749  
 743  750          desoutbuf.data = encrbuf;
 744  751  
 745  752          if (krb5_c_encrypt_length(kcmd_context, final_enctype,
 746  753                          use_ivecs ? (size_t)len + 4 : (size_t)len, &ret)) {
 747  754                  desoutbuf.length = ((size_t)-1);
 748  755                  goto err;
 749  756          } else {
 750  757                  desoutbuf.length = ret;
 751  758          }
 752  759  
 753  760          if (desoutbuf.length > MAXSIZE) {
 754  761                  (void) fprintf(stderr, gettext("Write size problem.\n"));
 755  762                  return (-1);
 756  763          }
 757  764  
 758  765          /*
 759  766           * Encrypt information
 760  767           */
 761  768          outputd.ciphertext.length = desoutbuf.length;
 762  769          outputd.ciphertext.data = (krb5_pointer)desoutbuf.data;
 763  770  
 764  771          cc = krb5_c_encrypt(kcmd_context, skey,
 765  772                          enc_keyusage_o[secondary],
 766  773                          use_ivecs ? encivec_o + secondary : 0,
 767  774                          &inputd, &outputd);
 768  775  
 769  776          if (cc) {
 770  777  err:
 771  778                  (void) fprintf(stderr, gettext("Write encrypt problem.\n"));
 772  779                  return (-1);
 773  780          }
 774  781  
 775  782          len_buf[0] = (len & 0xff000000) >> 24;
 776  783          len_buf[1] = (len & 0xff0000) >> 16;
 777  784          len_buf[2] = (len & 0xff00) >> 8;
 778  785          len_buf[3] = (len & 0xff);
 779  786          (void) write(fd, len_buf, 4);
 780  787  
 781  788          if (write(fd, desoutbuf.data, desoutbuf.length) != desoutbuf.length) {
 782  789                  (void) fprintf(stderr, gettext("Could not write "
 783  790                          "out all data.\n"));
 784  791                  return (-1);
 785  792          } else {
 786  793                  return (len);
 787  794          }
 788  795  }
  
    | 
      ↓ open down ↓ | 
    362 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX