See ChangeLog: Mon May 31 19:41:10 CEST 1999 Werner Koch
[gnupg.git] / util / secmem.c
index 44df08b..f48b0ed 100644 (file)
@@ -1,14 +1,14 @@
 /* secmem.c  - memory allocation from a secure heap
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998,1999 Free Software Foundation, Inc.
  *
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
  *
- * GNUPG is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
@@ -24,8 +24,8 @@
 #include <string.h>
 #include <errno.h>
 #include <stdarg.h>
+#include <unistd.h>
 #if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
-  #include <unistd.h>
   #include <sys/mman.h>
   #include <sys/types.h>
   #include <fcntl.h>
@@ -47,8 +47,7 @@ struct memblock_struct {
     unsigned size;
     union {
        MEMBLOCK *next;
-       long align_dummy;
-       char d[1];
+       PROPERLY_ALIGNED_TYPE aligned;
     } u;
 };
 
@@ -67,6 +66,16 @@ static unsigned cur_blocks;
 static int disable_secmem;
 static int show_warning;
 static int no_warning;
+static int suspend_warning;
+
+
+static void
+print_warn(void)
+{
+    if( !no_warning )
+       log_info(_("Warning: using insecure memory!\n"));
+}
+
 
 static void
 lock_pool( void *p, size_t n )
@@ -75,13 +84,26 @@ lock_pool( void *p, size_t n )
     uid_t uid;
     int err;
 
+    uid = getuid();
+
+  #ifdef HAVE_BROKEN_MLOCK
+    if( uid ) {
+       errno = EPERM;
+       err = errno;
+    }
+    else {
+       err = mlock( p, n );
+       if( err && errno )
+           err = errno;
+    }
+  #else
     err = mlock( p, n );
     if( err && errno )
        err = errno;
+  #endif
 
-    uid = getuid();
     if( uid && !geteuid() ) {
-       if( setuid( uid ) )
+       if( setuid( uid ) || getuid() != geteuid()  )
            log_fatal("failed to reset uid: %s\n", strerror(errno));
     }
 
@@ -137,7 +159,7 @@ init_pool( size_t n)
     }
     #endif
     if( pool == (void*)-1 )
-       log_error("can't mmap pool of %u bytes: %s - using malloc\n",
+       log_info("can't mmap pool of %u bytes: %s - using malloc\n",
                            (unsigned)poolsize, strerror(errno));
     else {
        pool_is_mmapped = 1;
@@ -168,27 +190,42 @@ compress_pool(void)
 void
 secmem_set_flags( unsigned flags )
 {
+    int was_susp = suspend_warning;
+
     no_warning = flags & 1;
+    suspend_warning = flags & 2;
+
+    /* and now issue the warning if it is not longer suspended */
+    if( was_susp && !suspend_warning && show_warning ) {
+       show_warning = 0;
+       print_warn();
+    }
 }
 
 unsigned
 secmem_get_flags(void)
 {
-    return no_warning ? 1:0;
+    unsigned flags;
+
+    flags  = no_warning      ? 1:0;
+    flags |= suspend_warning ? 2:0;
+    return flags;
 }
 
 void
 secmem_init( size_t n )
 {
     if( !n ) {
+      #ifndef HAVE_DOSISH_SYSTEM
        uid_t uid;
 
        disable_secmem=1;
        uid = getuid();
        if( uid != geteuid() ) {
-           if( setuid( uid ) )
+           if( setuid( uid ) || getuid() != geteuid() )
                log_fatal("failed to drop setuid\n" );
        }
+      #endif
     }
     else {
        if( n < DEFAULT_POOLSIZE )
@@ -207,12 +244,15 @@ secmem_malloc( size_t size )
     MEMBLOCK *mb, *mb2;
     int compressed=0;
 
-    if( !pool_okay )
-       log_bug("secmem not initialized\n");
-    if( show_warning ) {
+    if( !pool_okay ) {
+       log_info(
+        _("operation is not possible without initialized secure memory\n"));
+       log_info(_("(you may have used the wrong program for this task)\n"));
+       exit(2);
+    }
+    if( show_warning && !suspend_warning ) {
        show_warning = 0;
-       if( !no_warning )
-           log_info(_("Warning: using insecure memory!\n"));
+       print_warn();
     }
 
     /* blocks are always a multiple of 32 */
@@ -250,7 +290,7 @@ secmem_malloc( size_t size )
        max_alloced = cur_alloced;
     if( cur_blocks > max_blocks )
        max_blocks = cur_blocks;
-    return &mb->u.d;
+    return &mb->u.aligned.c;
 }
 
 
@@ -261,7 +301,7 @@ secmem_realloc( void *p, size_t newsize )
     size_t size;
     void *a;
 
-    mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.d));
+    mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
     size = mb->size;
     if( newsize < size )
        return p; /* it is easier not to shrink the memory */
@@ -282,8 +322,10 @@ secmem_free( void *a )
     if( !a )
        return;
 
-    mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.d));
+    mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
     size = mb->size;
+    /* This does not make much sense: probably this memory is held in the
+     * cache. We do it anyway: */
     memset(mb, 0xff, size );
     memset(mb, 0xaa, size );
     memset(mb, 0x55, size );