Пример #1
0
EXPIMP_TEMPLATE INCHI_API int INCHI_DECL GetINCHIKeyFromINCHI(const char* szINCHISource, 
                                                              const int xtra1,
                                                              const int xtra2,
                                                              char* szINCHIKey,
                                                              char* szXtra1,
                                                              char* szXtra2)
{
int ret = INCHIKEY_OK;
int ret1 = INCHIKEY_OK;
int cn;
size_t slen, i, j, jproto=0, ncp, pos_slash1=0;
char *str = NULL, *smajor = NULL, *sminor = NULL, 
     *sproto=NULL,
     *stmp = NULL, tmp[MINOUTLENGTH]; 
unsigned char 
    digest_major[32], digest_minor[32];     

char flagstd = 'S', /* standard key */
     flagnonstd = 'N', /* non-standard key */
     flagver = 'A', /* InChI v. 1 */
     flagproto = 'N'; /* no [de]protonization , by default */
int  nprotons;
/*
Protonization encoding:
N 0
O +1 P +2 Q +3 R +4 S +5 T +6 U +7 V +8 W +9 X +10 Y +11 Z +12
M -1 L-2 K -3 J -4 I -5 H -6 G -7 F -8 E -9 D -10 C -11 B -12 
A < -12 or > +12
*/
static const char *pplus = "OPQRSTUVWXYZ";
static const char *pminus = "MLKJIHGFEDCB";

int bStdFormat = 0;
size_t bytelen = 32;


    /* Check if input is a valid InChI string */

    /* .. non-empty */
    if (szINCHISource==NULL)
        return INCHIKEY_EMPTY_INPUT;
    
    slen = strlen(szINCHISource);
    
    /* .. has valid prefix */
    if (slen<LEN_INCHI_STRING_PREFIX+3)                         
        return INCHIKEY_INVALID_INCHI_PREFIX;    
    if (memcmp(szINCHISource,INCHI_STRING_PREFIX,LEN_INCHI_STRING_PREFIX))    
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. has InChI version 1 */
    /* if (!isdigit(szINCHISource[LEN_INCHI_STRING_PREFIX]) )  */
    if ( szINCHISource[LEN_INCHI_STRING_PREFIX] != '1' )  
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. optionally has a 'standard' flag character */
    pos_slash1 = LEN_INCHI_STRING_PREFIX+1;
    if (szINCHISource[pos_slash1]=='S')            
    {
        /* Standard InChI ==> standard InChIKey */
        bStdFormat = 1;
        pos_slash1++;
    }

    /* .. has trailing slash in the right place */
    if (szINCHISource[pos_slash1]!='/')            
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. the rest of source string contains at least one a..Z0.9 or slash */
    /* TODO: improve/add full string check */
    if (!isalnum(szINCHISource[pos_slash1+1] ) &&
       ( szINCHISource[pos_slash1+1]!='/' )     ) 
        return INCHIKEY_INVALID_INCHI;    


    /*^^^ Ok. Will use a local copy of the source. */
    
    extract_inchi_substring(&str, szINCHISource, slen);
    if (NULL==str)
    { 
        ret = INCHIKEY_NOT_ENOUGH_MEMORY; 
        goto fin; 
    }
    slen = strlen(str);


    /*^^^ Make buffers. */
    smajor = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==smajor)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    sminor = (char*) inchi_calloc( 2*slen + 2, sizeof(char)); /* we may double the length ... */ 
    if (NULL==sminor)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    stmp = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==stmp)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    sproto = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==sproto)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }


    szINCHIKey[0] = '\0';

    
    
    /*^^^ Extract the major block. */
    
    smajor[0]  = '\0';
    for (j = pos_slash1 + 1; j < slen-1; j++)
    {
        if (str[j]=='/')    
        {
            cn = str[j+1];
            switch (cn) 
            { 
                /* anything allowed from a major part */
                case 'c': case 'h': case 'q':   continue; 
                
                /* "/p"; protons now go to to special string, not to minor hash */
                case 'p':						jproto = j;
                                                continue;
                
                /* "/f",  "/r" : may not occur in stdInChI */
                case 'f': case 'r':		        if ( bStdFormat )
                                                {
                                                    ret = INCHIKEY_INVALID_STD_INCHI; 
                                                    goto fin;
                                                }
                                                break;
                
                /* anything allowed from a minor part */
                default:                        break; 
            }
            break;
        }
    }       
    j++;
    if (j==slen) 
        j++;
    else 
        j--;

    ncp=0;

    if (jproto)
        ncp = jproto - pos_slash1 - 1; 
    else
        ncp = j - pos_slash1 - 1; 
    

    /*^^^ Trim 'InChI=1[S]/' */
    memcpy(smajor,str+pos_slash1+1, ncp*sizeof(str[0]));
    smajor[ncp]='\0';


    /* Treat protonization */
    if (jproto)
    {
        /* 2009-01-07 fix bug/typo: assigned incorrect length to the protonation segment of 
        /* source string ( was sproto[ncp]='\0'; should be sproto[lenproto]='\0'; )  */
        int lenproto = j - jproto;
        if (lenproto<3)
        {	
            /* empty "/p", should not occur */
            ret = INCHIKEY_INVALID_INCHI; 
            goto fin;
        }
        
        memcpy(sproto,str+pos_slash1+ncp+1, lenproto*sizeof(str[0]));
        sproto[lenproto]='\0';
       
        nprotons = strtol( sproto+2, NULL, 10 );        
        
        if (nprotons > 0)
        {
            if (nprotons > 12) flagproto = 'A';
            else			   flagproto = pplus[nprotons-1];
        }
        else if (nprotons < 0)
        {
            if (nprotons < -12) flagproto = 'A';
            else				flagproto = pminus[-nprotons-1];
        }
        else
        {
            /* should never occur */
            ret = INCHIKEY_INVALID_STD_INCHI; 
            goto fin;
        }
    }



    /*^^^ Extract the minor block. */

    if (j != slen+1)    /*^^^ check that something exists at right.*/
    {
        ncp = slen-j; 
        memcpy(sminor,str+j, (ncp)*sizeof(str[0]));
        sminor[ncp]='\0';
    }
    else 
        sminor[0]='\0'; 
        

#if INCHIKEY_DEBUG 
    fprintf(stdout,"Source:  {%-s}\n",str);
    fprintf(stdout,"SMajor:  {%-s}\n",smajor);
    fprintf(stdout,"SMinor:  {%-s}\n",sminor);
    fprintf(stdout,"SProto:  {%-s}\n",sproto);
#endif      



    /*^^^ Compute and compose the InChIKey string. */


    /*^^^ Major hash sub-string. */    
    for( i = 0; i < 32; i++ ) 
        digest_major[i] = 0;            
    sha2_csum( (unsigned char *) smajor, (int) strlen(smajor), digest_major );    

    /* !!! */
    strcpy(tmp, base26_triplet_1(digest_major));
    strcpy(tmp, base26_triplet_2(digest_major));
    strcpy(tmp, base26_triplet_3(digest_major) );
    strcpy(tmp, base26_triplet_4(digest_major) );
    strcpy(tmp, base26_dublet_for_bits_56_to_64(digest_major));

    sprintf(tmp,"%-.3s%-.3s%-.3s%-.3s%-.2s", 
                base26_triplet_1(digest_major), base26_triplet_2(digest_major),
                base26_triplet_3(digest_major), base26_triplet_4(digest_major),
                base26_dublet_for_bits_56_to_64(digest_major));
    strcat(szINCHIKey, tmp);    
#if (INCHIKEY_DEBUG>1)
        fprint_digest(stderr, "Major hash, full SHA-256",digest_major);         
#endif  



    /*^^^ Minor hash sub-string. */
    for( i = 0; i < 32; i++ ) 
        digest_minor[i] = 0; 
    slen = strlen(sminor); 
    if ((slen>0)&&(slen<255)) 
    { 
        strcpy(stmp, sminor); 
        strcpy(sminor+slen,stmp); 
    }
    sha2_csum( (unsigned char *) sminor, (int) strlen(sminor), digest_minor );
#if (INCHIKEY_DEBUG>1)  
        fprint_digest(stderr, "Minor hash, full SHA-256",digest_minor);
#endif

    strcat(szINCHIKey, "-");
    sprintf(tmp,"%-.3s%-.3s%-.2s", 
        base26_triplet_1(digest_minor), 
        base26_triplet_2(digest_minor), 
        base26_dublet_for_bits_28_to_36(digest_minor));  
    strcat(szINCHIKey, tmp); 


    /* Append a standard/non-standard flag */
    slen = strlen(szINCHIKey);
    if ( bStdFormat )
        szINCHIKey[slen] = flagstd; 
    else
        szINCHIKey[slen] = flagnonstd; 

    /*^^^ Append InChI v.1 flag */
    szINCHIKey[slen+1] = flagver; 
    
    /*^^^ Append dash  */
    szINCHIKey[slen+2] = '-'; 
    
    /*^^^ Append protonization flag */
    szINCHIKey[slen+3] = flagproto; 
    szINCHIKey[slen+4] = '\0';


#if INCHIKEY_DEBUG 
    fprintf(stdout,"szINCHIKey:  {%-s}\n",szINCHIKey);
#endif

    /* Hash extensions */
    if ( xtra1 && szXtra1 )
    {
        get_xtra_hash_major_hex(digest_major, szXtra1);
#if INCHIKEY_DEBUG 
        fprintf(stderr,"XHash1=%-s\n",szXtra1);
        fprintf(stderr,"j=%-d\n",j);
#endif
    }
    if ( xtra2 && szXtra2 )
    {
        get_xtra_hash_minor_hex(digest_minor, szXtra2);
#if INCHIKEY_DEBUG 
        fprintf(stderr,"XHash2=%-s\n",szXtra2);
        fprintf(stderr,"j=%-d\n",j);
#endif
    }
        

fin:if (NULL!=str)      inchi_free(str);
    if (NULL!=smajor)   inchi_free(smajor);
    if (NULL!=sminor)   inchi_free(sminor);
    if (NULL!=stmp)     inchi_free(stmp);
    if (NULL!=sproto)   inchi_free(sproto);

    if ( (ret==INCHIKEY_OK) && (ret1!=INCHIKEY_OK) )
        ret = ret1;
    return ret;

}
extern int codesign_util(int argc, char * const *argv)
{
    int             result = 1, verbose = 0;
    char            ch;

    while ((ch = getopt(argc, argv, "v")) != -1)
    {
        switch (ch)
        {
        case 'v':
            verbose++;
            break;
        default:
            return 2; /* Trigger usage message. */
        }
    }
    
	argc -= optind;
	argv += optind;

    if (argc != 1)
        return 2; /* Trigger usage message. */

    CFArrayRef sigs = load_code_signatures(argv[0]);
    require(sigs, out);

    if (verbose >= 2)
        CFShow(sigs);

    CFIndex i, count = CFArrayGetCount(sigs);
    
    for (i = 0; i < count; i++) {
        CFDictionaryRef signature = CFArrayGetValueAtIndex(sigs, i);

        CFDataRef code_dir = CFDictionaryGetValue(signature, CFSTR("CodeDirectory"));
        const CS_CodeDirectory *cd = (CS_CodeDirectory *)CFDataGetBytePtr(code_dir);

        CFDataRef signed_data = CFDictionaryGetValue(signature, CFSTR("SignedData"));

        CFDataRef entitlements = CFDictionaryGetValue(signature, CFSTR("Entitlements"));
        CFDataRef entitlements_cd_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsCDHash"));
        CFDataRef entitlements_hash = CFDictionaryGetValue(signature, CFSTR("EntitlementsHash"));

        CFStringRef arch = CFDictionaryGetValue(signature, CFSTR("ARCH"));
        
        CFShow(arch);

        SecPolicyRef policy = SecPolicyCreateiPhoneApplicationSigning();

        if (signed_data) {
            if (SecCMSVerify(signed_data, code_dir, policy, NULL, NULL)) {
                fprintf(stderr, "Failed to verify signature\n");
                result = -1;
            } else
                fprintf(stderr, "Signature ok\n");

        } else
            fprintf(stderr, "Ad-hoc signed binary\n");

        if (entitlements_cd_hash) {
            if (entitlements_hash && entitlements_cd_hash && CFEqual(entitlements_hash, entitlements_cd_hash))
                fprintf(stderr, "Entitlements ok\n");
            else
                fprintf(stderr, "Entitlements modified\n");
        }

        if (verbose >= 2) {
            fprintf(stderr, "magic: 0x%x length: %u(%lu)\n", ntohl(cd->magic), ntohl(cd->length), CFDataGetLength(code_dir));
            fprintf(stderr, "code directory version/flags: 0x%x/0x%x special/code hash slots: %u/%u\n"
                "codelimit: %u hash size/type: %u/%u hash/ident offset: %u/%u\n",
                ntohl(cd->version), ntohl(cd->flags), ntohl(cd->nSpecialSlots), ntohl(cd->nCodeSlots),
                ntohl(cd->codeLimit), cd->hashSize, cd->hashType, ntohl(cd->hashOffset), ntohl(cd->identOffset));
            fprintf(stderr, "ident: '%s'\n", CFDataGetBytePtr(code_dir) + ntohl(cd->identOffset));

            uint32_t ix;
            uint8_t *hashes = (uint8_t *)CFDataGetBytePtr(code_dir) + ntohl(cd->hashOffset);
            for (ix = 0; ix < ntohl(cd->nSpecialSlots); ++ix) {
                fprint_digest(stderr, hashes, cd->hashSize);
                fprintf(stderr, "\n");
                hashes += cd->hashSize;
            }
        }

        if (verbose >= 1) {
            if (entitlements)
                fprintf(stderr, "Entitlements\n%.*s", (int)CFDataGetLength(entitlements)-8, CFDataGetBytePtr(entitlements)+8);
        }

        if (verbose >= 2) {
            if (entitlements_hash) {
                fprintf(stderr, "digest: ");
                fprint_digest(stderr, (uint8_t *)CFDataGetBytePtr(entitlements_hash), CC_SHA1_DIGEST_LENGTH);
                fprintf(stderr, "\n");
            }
        }
    }
    
    CFReleaseSafe(sigs);

    return result;
out:
    return -1;
}