LCOV - code coverage report
Current view: top level - lib/afs - afs_funcs.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 4 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Generate AFS tickets
       4             :  *  Copyright (C) Volker Lendecke 2003
       5             :  *
       6             :  *  This program is free software; you can redistribute it and/or modify
       7             :  *  it under the terms of the GNU General Public License as published by
       8             :  *  the Free Software Foundation; either version 3 of the License, or
       9             :  *  (at your option) any later version.
      10             :  *
      11             :  *  This program is distributed in the hope that it will be useful,
      12             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  *  GNU General Public License for more details.
      15             :  *
      16             :  *  You should have received a copy of the GNU General Public License
      17             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : #include "lib/afs/afs_funcs.h"
      22             : 
      23             : #ifdef WITH_FAKE_KASERVER
      24             : 
      25             : #define NO_ASN1_TYPEDEFS 1
      26             : 
      27             : #include "secrets.h"
      28             : #include "passdb.h"
      29             : #include "auth.h"
      30             : #include "../librpc/gen_ndr/ndr_netlogon.h"
      31             : #include "lib/afs/afs_settoken.h"
      32             : 
      33             : #include <afs/param.h>
      34             : #include <afs/stds.h>
      35             : #include <afs/auth.h>
      36             : #include <afs/venus.h>
      37             : #include <asm/unistd.h>
      38             : #include <openssl/des.h>
      39             : 
      40             : struct ClearToken {
      41             :         uint32 AuthHandle;
      42             :         char HandShakeKey[8];
      43             :         uint32 ViceId;
      44             :         uint32 BeginTimestamp;
      45             :         uint32 EndTimestamp;
      46             : };
      47             : 
      48             : static char *afs_encode_token(const char *cell, const DATA_BLOB ticket,
      49             :                               const struct ClearToken *ct)
      50             : {
      51             :         char *base64_ticket;
      52             :         char *result = NULL;
      53             : 
      54             :         DATA_BLOB key = data_blob(ct->HandShakeKey, 8);
      55             :         char *base64_key;
      56             :         TALLOC_CTX *mem_ctx;
      57             : 
      58             :         mem_ctx = talloc_stackframe();
      59             :         if (mem_ctx == NULL)
      60             :                 goto done;
      61             : 
      62             :         base64_ticket = base64_encode_data_blob(mem_ctx, ticket);
      63             :         if (base64_ticket == NULL)
      64             :                 goto done;
      65             : 
      66             :         base64_key = base64_encode_data_blob(mem_ctx, key);
      67             :         if (base64_key == NULL)
      68             :                 goto done;
      69             : 
      70             :         asprintf(&result, "%s\n%u\n%s\n%u\n%u\n%u\n%s\n", cell,
      71             :                  ct->AuthHandle, base64_key, ct->ViceId, ct->BeginTimestamp,
      72             :                  ct->EndTimestamp, base64_ticket);
      73             : 
      74             :         DEBUG(10, ("Got ticket string:\n%s\n", result));
      75             : 
      76             : done:
      77             :         TALLOC_FREE(mem_ctx);
      78             : 
      79             :         return result;
      80             : }
      81             : 
      82             : /* Create a ClearToken and an encrypted ticket. ClearToken has not yet the
      83             :  * ViceId set, this should be set by the caller. */
      84             : 
      85             : static bool afs_createtoken(const char *username, const char *cell,
      86             :                             DATA_BLOB *ticket, struct ClearToken *ct)
      87             : {
      88             :         fstring clear_ticket;
      89             :         char *p = clear_ticket;
      90             :         uint32 len;
      91             :         uint32 now;
      92             : 
      93             :         struct afs_key key;
      94             :         des_key_schedule key_schedule;
      95             : 
      96             :         if (!secrets_init())
      97             :                 return false;
      98             : 
      99             :         if (!secrets_fetch_afs_key(cell, &key)) {
     100             :                 DEBUG(1, ("Could not fetch AFS service key\n"));
     101             :                 return false;
     102             :         }
     103             : 
     104             :         ct->AuthHandle = key.kvno;
     105             : 
     106             :         /* Build the ticket. This is going to be encrypted, so in our
     107             :            way we fill in ct while we still have the unencrypted
     108             :            form. */
     109             : 
     110             :         p = clear_ticket;
     111             : 
     112             :         /* The byte-order */
     113             :         *p = 1;
     114             :         p += 1;
     115             : 
     116             :         /* "Alice", the client username */
     117             :         strncpy(p, username, sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
     118             :         p += strlen(p)+1;
     119             :         strncpy(p, "", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
     120             :         p += strlen(p)+1;
     121             :         strncpy(p, cell, sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
     122             :         p += strlen(p)+1;
     123             : 
     124             :         /* Alice's network layer address. At least Openafs-1.2.10
     125             :            ignores this, so we fill in a dummy value here. */
     126             :         SIVAL(p, 0, 0);
     127             :         p += 4;
     128             : 
     129             :         /* We need to create a session key */
     130             :         generate_random_buffer((uint8_t *)p, 8);
     131             : 
     132             :         /* Our client code needs the the key in the clear, it does not
     133             :            know the server-key ... */
     134             :         memcpy(ct->HandShakeKey, p, 8);
     135             : 
     136             :         p += 8;
     137             : 
     138             :         /* This is a kerberos 4 life time. The life time is expressed
     139             :          * in units of 5 minute intervals up to 38400 seconds, after
     140             :          * that a table is used up to lifetime 0xBF. Values between
     141             :          * 0xC0 and 0xFF is undefined. 0xFF is defined to be the
     142             :          * infinite time that never expire.
     143             :          *
     144             :          * So here we cheat and use the infinite time */
     145             :         *p = 255;
     146             :         p += 1;
     147             : 
     148             :         /* Ticket creation time */
     149             :         now = time(NULL);
     150             :         SIVAL(p, 0, now);
     151             :         ct->BeginTimestamp = now;
     152             : 
     153             :         if(lp_afs_token_lifetime() == 0)
     154             :                 ct->EndTimestamp = NEVERDATE;
     155             :         else
     156             :                 ct->EndTimestamp = now + lp_afs_token_lifetime();
     157             : 
     158             :         if (((ct->EndTimestamp - ct->BeginTimestamp) & 1) == 1) {
     159             :                 ct->BeginTimestamp += 1; /* Lifetime must be even */
     160             :         }
     161             :         p += 4;
     162             : 
     163             :         /* And here comes Bob's name and instance, in this case the
     164             :            AFS server. */
     165             :         strncpy(p, "afs", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
     166             :         p += strlen(p)+1;
     167             :         strncpy(p, "", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
     168             :         p += strlen(p)+1;
     169             : 
     170             :         /* And zero-pad to a multiple of 8 bytes */
     171             :         len = PTR_DIFF(p, clear_ticket);
     172             :         if (len & 7) {
     173             :                 uint32 extra_space = 8-(len & 7);
     174             :                 memset(p, 0, extra_space);
     175             :                 p+=extra_space;
     176             :         }
     177             :         len = PTR_DIFF(p, clear_ticket);
     178             : 
     179             :         des_key_sched((const_des_cblock *)key.key, key_schedule);
     180             :         des_pcbc_encrypt((const unsigned char*) clear_ticket,
     181             :                          (unsigned char*) clear_ticket,
     182             :                          len, key_schedule, (C_Block *)key.key, 1);
     183             : 
     184             :         ZERO_STRUCT(key);
     185             : 
     186             :         *ticket = data_blob(clear_ticket, len);
     187             : 
     188             :         return true;
     189             : }
     190             : 
     191             : char *afs_createtoken_str(const char *username, const char *cell)
     192             : {
     193             :         DATA_BLOB ticket;
     194             :         struct ClearToken ct;
     195             :         char *result;
     196             : 
     197             :         if (!afs_createtoken(username, cell, &ticket, &ct))
     198             :                 return NULL;
     199             : 
     200             :         result = afs_encode_token(cell, ticket, &ct);
     201             : 
     202             :         data_blob_free(&ticket);
     203             : 
     204             :         return result;
     205             : }
     206             : 
     207             : /*
     208             :   This routine takes a radical approach completely bypassing the
     209             :   Kerberos idea of security and using AFS simply as an intelligent
     210             :   file backend. Samba has persuaded itself somehow that the user is
     211             :   actually correctly identified and then we create a ticket that the
     212             :   AFS server hopefully accepts using its KeyFile that the admin has
     213             :   kindly stored to our secrets.tdb.
     214             : 
     215             :   Thanks to the book "Network Security -- PRIVATE Communication in a
     216             :   PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner
     217             :   Kerberos 4 tickets are not really hard to construct.
     218             : 
     219             :   For the comments "Alice" is the User to be auth'ed, and "Bob" is the
     220             :   AFS server.  */
     221             : 
     222             : bool afs_login(connection_struct *conn)
     223             : {
     224             :         const struct loadparm_substitution *lp_sub =
     225             :                 loadparm_s3_global_substitution();
     226             :         DATA_BLOB ticket;
     227             :         char *afs_username = NULL;
     228             :         char *cell = NULL;
     229             :         bool result;
     230             :         char *ticket_str = NULL;
     231             :         const struct dom_sid *user_sid;
     232             :         TALLOC_CTX *ctx = talloc_tos();
     233             :         struct dom_sid_buf buf;
     234             : 
     235             :         struct ClearToken ct;
     236             : 
     237             :         afs_username = talloc_strdup(ctx,
     238             :                                 lp_afs_username_map());
     239             :         if (!afs_username) {
     240             :                 return false;
     241             :         }
     242             : 
     243             :         afs_username = talloc_sub_advanced(ctx,
     244             :                                 lp_servicename(ctx, lp_sub, SNUM(conn)),
     245             :                                 conn->session_info->unix_info->unix_name,
     246             :                                 conn->connectpath,
     247             :                                 conn->session_info->unix_token->gid,
     248             :                                 conn->session_info->unix_info->sanitized_username,
     249             :                                 conn->session_info->info->domain_name,
     250             :                                 afs_username);
     251             :         if (!afs_username) {
     252             :                 return false;
     253             :         }
     254             : 
     255             :         user_sid = &conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     256             :         afs_username = talloc_string_sub(talloc_tos(),
     257             :                                         afs_username,
     258             :                                         "%s",
     259             :                                         dom_sid_str_buf(user_sid, &buf));
     260             :         if (!afs_username) {
     261             :                 return false;
     262             :         }
     263             : 
     264             :         /* The pts command always generates completely lower-case user
     265             :          * names. */
     266             :         if (!strlower_m(afs_username)) {
     267             :                 return false;
     268             :         }
     269             : 
     270             :         cell = strchr(afs_username, '@');
     271             : 
     272             :         if (cell == NULL) {
     273             :                 DEBUG(1, ("AFS username doesn't contain a @, "
     274             :                           "could not find cell\n"));
     275             :                 return false;
     276             :         }
     277             : 
     278             :         *cell = '\0';
     279             :         cell += 1;
     280             : 
     281             :         DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
     282             :                    afs_username, cell));
     283             : 
     284             :         if (!afs_createtoken(afs_username, cell, &ticket, &ct))
     285             :                 return false;
     286             : 
     287             :         /* For which Unix-UID do we want to set the token? */
     288             :         ct.ViceId = getuid();
     289             : 
     290             :         ticket_str = afs_encode_token(cell, ticket, &ct);
     291             : 
     292             :         result = afs_settoken_str(ticket_str);
     293             : 
     294             :         SAFE_FREE(ticket_str);
     295             : 
     296             :         data_blob_free(&ticket);
     297             : 
     298             :         return result;
     299             : }
     300             : 
     301             : #else
     302             : 
     303           0 : bool afs_login(connection_struct *conn)
     304             : {
     305           0 :         return true;
     306             : }
     307             : 
     308           0 : char *afs_createtoken_str(const char *username, const char *cell)
     309             : {
     310           0 :         return NULL;
     311             : }
     312             : 
     313             : #endif /* WITH_FAKE_KASERVER */

Generated by: LCOV version 1.14