Main Page | Data Structures | File List | Data Fields | Globals

ss-util.c

Go to the documentation of this file.
00001 
00008 /* ss-util.c - Secure Storage utility function
00009  * ====================================================================
00010  * Copyright (c) Giordano Scuderi, Unico SRL.  All rights reserved.
00011  *
00012  * Redistribution and use in source and binary forms, with or without
00013  * modification, are permitted provided that the following conditions
00014  * are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright
00017  *    notice, this list of conditions and the following disclaimer. 
00018  *
00019  * 2. Redistributions in binary form must reproduce the above copyright
00020  *    notice, this list of conditions and the following disclaimer in
00021  *    the documentation and/or other materials provided with the
00022  *    distribution.
00023  *
00024  * 3. All advertising materials mentioning features or use of this
00025  *    software must display the following acknowledgment:
00026  *    "This product includes software developed by Giordano Scuderi
00027  *    for Unico SRL"
00028  *
00029  * 4. The names "Secure Storage" must not be used to
00030  *    endorse or promote products derived from this software without
00031  *    prior written permission. For written permission, please contact
00032  *    gscuderi@unicosrl.it.
00033  *
00034  * 5. Products derived from this software may not be called "Secure Storage"
00035  *    nor may "Secure Storage" appear in their names without prior written
00036  *    permission of Giordano Scuderi (Unico SRL).
00037  *
00038  * 6. Redistributions of any form whatsoever must retain the following
00039  *    acknowledgment:
00040  *    "This product includes software developed by Giordano Scuderi
00041  *    for Unico SRL"
00042  *
00043  * THIS SOFTWARE IS PROVIDED BY UNICO SRL ``AS IS'' AND ANY
00044  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00045  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00046  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNICO SRL OR
00047  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00048  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00049  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00050  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00051  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00052  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00053  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00054  * OF THE POSSIBILITY OF SUCH DAMAGE.
00055  * ====================================================================
00056  *
00057  * "This product includes software developed by the OpenSSL Project
00058  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
00059  * 
00060  */
00061 
00062 #ifdef __cplusplus
00063 extern "C" {
00064 #endif
00065 
00066 #include <sys/mman.h>
00067 #if defined(_WIN32)
00068 #include <io.h>
00069 #else
00070 #include <unistd.h>
00071 #endif
00072 #include <assert.h>
00073 #include <sys/types.h>
00074 #include <sys/stat.h>
00075 #include <errno.h>
00076 #include <stdio.h>
00077 #include <string.h>
00078 #include <stdlib.h>
00079 #include <fcntl.h>
00080 #include <openssl/rand.h>
00081 //require e2fsprogs-devel
00082 #include <uuid/uuid.h>
00083 //end require
00084 #include "lcg_util.h"
00085 #include "ss-util.h"
00086 #include "keystore_client.h"
00087 
00088 #ifdef __cplusplus
00089 } /* closing brace for extern "C" */
00090 #endif  
00091 
00092 int securestorage_nerr = 56;
00093 extern int errno;
00094 
00095 /* increment counter (128-bit int) by 1 */
00096 //static 
00097 void ivec_inc(unsigned char *counter) {
00098         unsigned long c;
00099 
00100         /* Grab bottom dword of counter and increment */
00101         c = GETU32(counter + 12);
00102         c++;    c &= 0xFFFFFFFF;
00103         PUTU32(counter + 12, c);
00104         
00105         /* if no overflow, we're done */
00106         if (c)
00107                 return;
00108 
00109         /* Grab 1st dword of counter and increment */
00110         c = GETU32(counter +  8);
00111         c++;    c &= 0xFFFFFFFF;
00112         PUTU32(counter +  8, c);
00113         
00114         /* if no overflow, we're done */
00115         if (c)
00116                 return;
00117 
00118         /* Grab 2nd dword of counter and increment */
00119         c = GETU32(counter +  4);
00120         c++;    c &= 0xFFFFFFFF;
00121         PUTU32(counter +  4, c);
00122         
00123         /* if no overflow, we're done */
00124         if (c)
00125                 return;
00126 
00127         /* Grab top dword of counter and increment */
00128         c = GETU32(counter +  0);
00129         c++;    c &= 0xFFFFFFFF;
00130         PUTU32(counter +  0, c);
00131 }
00132 
00133 
00134 /* decrement counter (128-bit int) by 1 */
00135 //static 
00136 void ivec_dec(unsigned char *counter) {
00137         unsigned long c;
00138         
00139         /* Grab bottom dword of counter and decrement */
00140         c = GETU32(counter + 12);
00141         if (!c) {
00142                 c--;    c &= 0xFFFFFFFF;
00143                 PUTU32(counter + 12, c);
00144         } else {
00145                 c--;    c &= 0xFFFFFFFF;
00146                 PUTU32(counter + 12, c);
00147                 return;
00148         }
00149 
00150         /* Grab 1st dword of counter and decrement */
00151         c = GETU32(counter +  8);
00152         if (!c) {
00153                 c--;    c &= 0xFFFFFFFF;
00154                 PUTU32(counter +  8, c);
00155         } else {
00156                 c--;    c &= 0xFFFFFFFF;
00157                 PUTU32(counter +  8, c);
00158                 return;
00159         }
00160 
00161         /* Grab 2nd dword of counter and decrement */
00162         c = GETU32(counter +  4);
00163         if (!c) {
00164                 c--;    c &= 0xFFFFFFFF;
00165                 PUTU32(counter +  4, c);
00166         } else {
00167                 c--;    c &= 0xFFFFFFFF;
00168                 PUTU32(counter +  4, c);
00169                 return;
00170         }
00171 
00172         /* Grab top dword of counter and decrement */
00173         c = GETU32(counter +  0);
00174         c--;    c &= 0xFFFFFFFF;
00175         PUTU32(counter +  0, c);
00176         
00177 }
00178 
00179 
00180 /* The input encrypted as though 128bit counter mode is being
00181  * used.  The extra state information to record how much of the
00182  * 128bit block we have used is contained in *num, and the
00183  * encrypted counter is kept in ecount_buf.  Both *num and
00184  * ecount_buf must be initialised with zeros before the first
00185  * call to securestorage_AES_ctr().
00186  *
00187  * This algorithm assumes that the counter is in the x lower bits
00188  * of the IV (ivec), and that the application has full control over
00189  * overflow and the rest of the IV.  This implementation takes NO
00190  * responsability for checking that the counter doesn't overflow
00191  * into the rest of the IV when incremented.
00192  */
00193 void securestorage_AES_ctr(const unsigned char *in, unsigned char *out,
00194         const unsigned long length, const AES_KEY *key,
00195         unsigned char ivec[AES_BLOCK_SIZE],
00196         unsigned char ecount_buf[AES_BLOCK_SIZE],
00197         unsigned int *num) {
00198 
00199         unsigned int n;
00200         unsigned long l=length;
00201 
00202         assert(in && out && key && num);
00203         assert(*num < AES_BLOCK_SIZE);
00204 
00205         n = *num;
00206 
00207         while (l--) {
00208                 if (n == 0) {
00209                         AES_encrypt(ivec, ecount_buf, key);
00210                         ivec_inc(ivec);
00211                 }
00212                 *(out++) = *(in++) ^ ecount_buf[n];
00213                 n = (n+1) % AES_BLOCK_SIZE;
00214         }
00215 
00216         *num=n;
00217 }
00218 
00219 
00220  /******************************************************************************
00221  * Lock memory
00222  ******************************************************************************/
00223  size_t lock_memory(char *addr, size_t size) {
00224         unsigned long page_offset, page_size;
00225         page_size = sysconf(_SC_PAGE_SIZE);
00226         page_offset = (unsigned long) addr % page_size;
00227         addr -= page_offset;  /* Adjust addr to page boundary */
00228         size += page_offset;  /* Adjust size with page_offset */
00229         return ( mlock(addr, size) );  /* Lock the memory */
00230  }
00231 
00232 
00233  /******************************************************************************
00234  * Unlock memory
00235  ******************************************************************************/
00236  size_t unlock_memory(char *addr, size_t size) {
00237         unsigned long page_offset, page_size;
00238         page_size = sysconf(_SC_PAGE_SIZE);
00239         page_offset = (unsigned long) addr % page_size;
00240         addr -= page_offset;  /* Adjust addr to page boundary */
00241         size += page_offset;  /* Adjust size with page_offset */
00242         return ( munlock(addr, size) );  /* Unlock the memory */
00243  }
00244 
00245 
00246 /******************************************************************************
00247  * Generate random data function
00248  * This function generate random data for the specified size, for using it on encryption
00249  *      process.
00250  * 
00251  ******************************************************************************/
00252  int ss_rand (int size, unsigned char *out) {
00253  
00254         int i, c;
00255         unsigned char temp[(size/2)+1];
00256         const char hex[] = "0123456789ABCDEF";
00257         
00258         if ( size <= 0 ) {
00259                 errno = EINVAL;
00260                 return (-2);
00261         }
00262         if (!out) {
00263                 errno = EINVAL;
00264                 return (-1);
00265         }
00266         /* Do Rand initialization */
00267         if (!RAND_load_file("/dev/urandom", 1)) {
00268                 int errno_save = errno;
00269                 RAND_cleanup();
00270                 errno = errno_save;
00271                 return (-3);
00272         }
00273         // Generate random data
00274         RAND_bytes((unsigned char *)temp, (size/2));
00275         
00276         c = size/2;
00277         
00278         for (i = 0; i < c; i++) {
00279                 out[i*2] = hex[temp[i] >> 4];
00280                 out[i*2+1] = hex[temp[i] & 15];
00281         }
00282 
00283         return (0);     
00284  }
00285 
00286  
00287  /******************************************************************************
00288  * Generate SURL
00289  * This function generate a valid SURL ( in srm:// format )
00290  * 
00291  ******************************************************************************/
00292  int ss_generate_surl (char **dest_surl, char *dest_file, char *vo, char *guid) {
00293         
00294         //Variable definition
00295         char timestr[11];
00296         struct tm *tm;
00297         char *surl;
00298         time_t current_time;
00299         char guid_f[37];
00300         uuid_t uuid;
00301         char dir_path[256];
00302         char *ce_ap, *sa_root, *sa_path;
00303         char *errbuf2=NULL;
00304         int errbufsz2 = 0;
00305         char setype[8];
00306         
00307         if (NULL == ( surl = calloc(1, 512+1)) ) {
00308                 errno = ENOMEM;
00309                 return (-1);
00310         }
00311         if(get_sa_path (dest_file, vo, &sa_path, &sa_root, errbuf2, errbufsz2) < 0) {
00312                 int errno_save = errno;
00313                 free(surl);
00314                 errno = errno_save;
00315                 return (-2);
00316         }
00317         if(sa_path != NULL) {
00318                 if (strcmp (setype, "disk") == 0) {
00319                         sprintf (dir_path, "sfn://%s%s%s", dest_file, *sa_path=='/'?"":"/", sa_path);
00320                 }
00321                 else {
00322                         sprintf (dir_path, "srm://%s%s%s", dest_file, *sa_path=='/'?"":"/", sa_path);
00323                 }
00324         }
00325         else {
00326                 if (strcmp (setype, "disk") == 0) {
00327                         if (get_ce_apx (dest_file, &ce_ap, errbuf2, errbufsz2) < 0) {
00328                                         int errno_save = errno;
00329                                         free(surl);
00330                                         errno = errno_save;
00331                                         return (-3);
00332                         }
00333                         sprintf (dir_path, "sfn://%s%s%s%s%s", dest_file, 
00334                         *ce_ap=='/'?"":"/", ce_ap, 
00335                         *sa_root=='/'?"":"/", sa_root);
00336                         free (ce_ap);
00337                 }
00338                 else {
00339                         sprintf (dir_path, "srm://%s%s%s", dest_file, *sa_root=='/'?"":"/", sa_root); }
00340         }
00341         free (sa_path); free (sa_root);
00342         (void) time (&current_time);
00343         tm = localtime (&current_time);
00344         strftime (timestr, 11, "%F", tm);
00345         uuid_generate (uuid);
00346         uuid_unparse (uuid, guid_f);
00347         if (guid == NULL)
00348         sprintf (surl, "%s/generated/%s/file%s", dir_path, timestr, guid_f);
00349     else
00350         sprintf (surl, "%s/generated/%s/file%s", dir_path, timestr, guid);
00351     
00352     *dest_surl = surl;
00353     return 0;
00354   }
00355 
00356  
00357  /******************************************************************************
00358  * Get LFC Home
00359  * This function add LFC_HOME To your current LFN 
00360  * 
00361  ******************************************************************************/
00362  int ss_get_lfchome ( const char *input_lfn, char **lfn_new ) {
00363         
00364         //Variable definition
00365         char cattype[8];
00366         char *cat_type;
00367         char lfn[LCG_MAXPATHLEN+5];
00368         char *p;
00369         int strip=0;
00370         char *lfn_local;
00371         const char *input_lfn_tmp = input_lfn;
00372         
00373         if(get_cat_type (&cat_type) < 0) {
00374                 return (-1);
00375         }
00376         strcpy (cattype, cat_type);
00377         free (cat_type);
00378         
00379         /* Add LFC_HOME to input lfn */
00380         if(strcmp(cattype , "lfc") == 0) {
00381                 if (strncmp (input_lfn_tmp, "lfn:", 4) == 0) {
00382                         input_lfn_tmp += 4;
00383                         //strip off backslash
00384                         if ( strncmp(input_lfn_tmp,"/",1)==0 ) {
00385                                 while ( strncmp(input_lfn_tmp,"/",1)==0) {
00386                                         input_lfn_tmp+=1;
00387                                         strip++;
00388                                 }
00389                                 input_lfn_tmp-=1; //Only one '/' is allowed
00390                                 strip--;
00391                         }
00392                         // Add LFN prefix to path and return
00393                 if (strncmp (input_lfn_tmp, "/grid", 5) == 0 ) {
00394                         sprintf (lfn, "lfn:%s", input_lfn_tmp);
00395                         lfn_local = calloc(1,strlen(lfn)+1);
00396                                 strncpy(lfn_local, lfn, strlen(lfn));
00397                                 *lfn_new = lfn_local;
00398                         return 0;
00399                 } else if ( (strncmp(input_lfn_tmp,"/",1)==0) && (getenv("LFC_HOME")==NULL) ) {
00400                                 errno = SS_EINVALLFN;
00401                                 return (-2);
00402                         } else {
00403                                 p = getenv ("LFC_HOME");
00404                                 if(p == NULL) {
00405                                         errno = SS_EINVALLFN;
00406                                         return (-3);
00407                                 } else if ( strlen (p) + strlen (input_lfn_tmp) + 1 > LCG_MAXPATHLEN ) {
00408                                         errno = SS_ENAMETOOLONG;
00409                                         return (-4);
00410                                 } else {
00411                                         if ( strncmp(input_lfn_tmp,"/",1) == 0 )
00412                                                 input_lfn_tmp++;
00413                                         sprintf (lfn, "lfn:%s/%s", p, input_lfn_tmp);
00414                                         lfn_local = calloc(1,strlen(lfn)+1);
00415                                         strncpy(lfn_local, lfn, strlen(lfn));
00416                                 }
00417                         }
00418                 } else {
00419                         errno = SS_EINVALLFN;
00420                         return (-5);
00421                 }
00422         } else {
00423                 errno = SS_EINVALLFN;
00424                 return (-6);
00425         }
00426         
00427         *lfn_new = lfn_local;
00428         return 0;
00429  }
00430 
00431 
00432  /******************************************************************************
00433  * Get SURL
00434  * This function get the SURL for the input LFN given
00435  * 
00436  ******************************************************************************/
00437  int ss_get_surl ( char *lfn, char **surl, char *vo, char *se, int insecure ) {
00438 
00439         //Variable definition
00440         char **pfns;
00441         int x;
00442         
00443         // Get the replica's SURL
00444         if (strncmp (lfn, "lfn:", 4) == 0) {
00445                 if (lcg_lr (lfn, vo, NULL, insecure, &pfns) < 0) {
00446                         return (-1);
00447                 }
00448                 // Verify if exist at least one replica
00449                 if (pfns[0]== NULL) {
00450                         errno = SS_ENOENT;
00451                         return (-2);
00452                 } else {
00453                         //If se not specified then find the first available replica
00454                         if (se == NULL){
00455                                 *surl = strdup(pfns[0]);                                
00456                         } else {
00457                                 int g = strcspn(se, "\n");
00458                                 for (x=0;pfns[x]!=NULL;x++){
00459                                         pfns[x]+=6;
00460                                         if (strncmp (pfns[x], se, g) == 0){
00461                                                 pfns[x]-=6;
00462                                                 *surl = strdup(pfns[x]);
00463                                                 break;
00464                                         }
00465                                         pfns[x]-=6;
00466                                 }
00467                                 //No entry has been found in specified se
00468                                 if (pfns[x] == NULL){
00469                                         for(x=0;pfns[x]!=NULL;x++) {
00470                                                 free(pfns[x]);
00471                                         }
00472                                         free(pfns);
00473                                         errno = SS_ENOENT;
00474                                         return (-1);
00475                                 }
00476                         }
00477                         for(x=0;pfns[x]!=NULL;x++) {
00478                                 free(pfns[x]);
00479                         }
00480                         free(pfns);
00481                         if ( *surl==NULL) {
00482                                 errno = ENOMEM;
00483                                 return (-1);
00484                         }
00485                 }
00486         }
00487         else if ( (strncmp (lfn, "srm:", 4) == 0)) {
00488                 errno = SS_EINVALLFN;
00489                 return (-1);
00490         } else {
00491                 errno = SS_EINVALLFN;
00492                 return (-1);
00493         }
00494         return 0;               
00495  }
00496 
00497 
00498  /******************************************************************************
00499  * Check LFN existence
00500  * This function check if provided lfn exist in LFC Catalog.
00501  * 
00502  ******************************************************************************/
00503  int ss_check_lfn ( char *lfn, char *vo ) {
00504 
00505         //Variable definition
00506         char **pfns;
00507         int x;
00508         int insecure=0;
00509         int errno_save;
00510         
00511         // Get the replica's SURL
00512         if (strncmp (lfn, "lfn:", 4) == 0) {
00513                 if (lcg_lr (lfn, vo, NULL, insecure, &pfns) < 0) {
00514                         errno_save = errno;
00515                         if  (errno_save == ENOENT) {
00516                                 return (0);
00517                         } else {
00518                                 errno = errno_save;
00519                                 return(-1);
00520                         }
00521                 }
00522                 if (pfns[0] != NULL) {
00523                         for(x=0;pfns[x]!=NULL;x++) {
00524                                 free(pfns[x]);
00525                         }
00526                         free(pfns);
00527                 }
00528         }
00529         else if ( (strncmp (lfn, "srm:", 4) == 0)) {
00530                 errno = SS_EINVALLFN;
00531                 return (-1);
00532         } else {
00533                 errno = SS_EINVALLFN;
00534                 return (-1);
00535         }
00536         return (1);     
00537  }
00538 
00539 
00540 
00541  /******************************************************************************
00542  * Return descriptive string of error for errnum provided
00543  * 
00544  * 
00545  ******************************************************************************/ 
00546 const char *securestorage_error(int errnum) {
00547         //extern int securestorage_nerr;
00548         extern char *ss_errlist[];
00549         if (errnum < 10000 && errnum < sys_nerr ) {
00550                 //extern int sys_nerr;
00551                 //extern char *sys_errlist[];
00552                 return(sys_errlist[errnum]);
00553         }
00554         int errnum_tmp = errnum - 10000;
00555         static char message[] = "Unknown error (100001234567890)";
00556         if (errnum_tmp >= securestorage_nerr) {
00557                 snprintf(message, sizeof(message), "Unknown error (%d)", errnum_tmp);
00558                 return(message);
00559         } else {
00560                 return(ss_errlist[errnum_tmp]);
00561         }
00562 }

Generated on Wed May 30 09:56:30 2007 for Secure Storage Service by doxygen 1.3.5