coolkey/src/coolkey machdep.cpp, 1.8, 1.9 slot.cpp, 1.14, 1.15
by Robert Relyea
Author: rrelyea
Update of /cvs/dirsec/coolkey/src/coolkey
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv8085
Modified Files:
machdep.cpp slot.cpp
Log Message:
Unix safe open code for the cache
Index: machdep.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/machdep.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- machdep.cpp 4 Aug 2010 16:21:13 -0000 1.8
+++ machdep.cpp 8 Sep 2010 20:55:30 -0000 1.9
@@ -236,6 +236,73 @@
}
}
+/*
+ * The cache directory is shared and accessible by anyone, make
+ * sure the cache file we are opening is really a valid cache file.
+ */
+int safe_open(char *path, int flags, int mode, int size)
+{
+ struct stat buf;
+ int fd, ret;
+
+ fd = open (path, flags|O_NOFOLLOW, mode);
+
+ if (fd < 0) {
+ return fd;
+ }
+
+ ret = fstat(fd, &buf);
+ if (ret < 0) {
+ close (fd);
+ return ret;
+ }
+
+ /* our cache files are pretty specific, make sure we are looking
+ * at the correct one */
+
+ /* first, we should own the file ourselves, don't open a file
+ * that someone else wanted us to see. */
+ if (buf.st_uid != getuid()) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* next, there should only be one link in this file. Don't
+ * use this code to trash another file */
+ if (buf.st_nlink != 1) {
+ close(fd);
+ errno = EMLINK;
+ return -1;
+ }
+
+ /* next, This better be a regular file */
+ if (!S_ISREG(buf.st_mode)) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* if the permissions don't match, something is wrong */
+ if ((buf.st_mode & 03777) != mode) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* finally the file should be the correct size. This
+ * check isn't so much to protect from an attack, as it is to
+ * detect a corrupted cache file */
+ if (buf.st_size != size) {
+ close(fd);
+ errno = EACCES;
+ return -1;
+ }
+
+ /* OK, the file checked out, ok to continue */
+ return fd;
+}
+
SHMem::SHMem(): shmemData(0) {}
SHMem *
@@ -259,7 +326,7 @@
return NULL;
}
int mask = umask(0);
- int ret = mkdir (MEMSEGPATH, 1777);
+ int ret = mkdir (MEMSEGPATH, 01777);
umask(mask);
if ((ret == -1) && (errno != EEXIST)) {
delete shmemData;
@@ -284,6 +351,7 @@
if (shmemData->fd >= 0) {
char *buf;
int len = size+RESERVED_OFFSET;
+ int ret;
buf = (char *)calloc(1,len);
if (!buf) {
@@ -294,11 +362,20 @@
delete shmemData;
return NULL;
}
- write(shmemData->fd,buf,len);
+ ret = write(shmemData->fd,buf,len);
+ if (ret != len) {
+ unlink(shmemData->fd,buf,len);
+#ifdef FULL_CLEANUP
+ flock(shmemData->fd, LOCK_UN);
+#endif
+ delete shmemData;
+ return NULL;
+ }
free(buf);
} else if (errno == EEXIST) {
needInit = false;
- shmemData->fd = open(shmemData->path,O_RDWR|O_EXLOCK|O_NOFOLLOW, mode);
+ shmemData->fd = safe_open(shmemData->path,O_RDWR|O_EXLOCK, mode,
+ size+RESERVED_OFFSET);
}
if (shmemData->fd < 0) {
delete shmemData;
Index: slot.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/slot.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- slot.cpp 8 Sep 2010 20:14:41 -0000 1.14
+++ slot.cpp 8 Sep 2010 20:55:31 -0000 1.15
@@ -680,13 +680,7 @@
log->log("CoolKey Select failed 0x%x\n", status);
status = getCACAid();
if (status != CKYSUCCESS) {
- log->log("CAC Select failed 0x%x\n", status);
- if (status == CKYSCARDERR) {
- log->log("CAC Card Failure 0x%x\n",
- CKYCardConnection_GetLastError(conn));
- disconnect();
- }
- return;
+ goto loser;
}
state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;
/* skip the read of the cuid. We really don't need it and,
13 years, 7 months
coolkey/src/coolkey object.cpp, 1.4, 1.5 slot.cpp, 1.13, 1.14 slot.h, 1.3, 1.4
by Robert Relyea
Author: rrelyea
Update of /cvs/dirsec/coolkey/src/coolkey
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv6855/src/coolkey
Modified Files:
object.cpp slot.cpp slot.h
Log Message:
New CAC support
Index: object.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/object.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- object.cpp 16 Sep 2009 23:56:40 -0000 1.4
+++ object.cpp 8 Sep 2010 20:14:40 -0000 1.5
@@ -505,6 +505,10 @@
unsigned char tag;
unsigned int used_length= 0;
+ if(!buf) {
+ return NULL;
+ }
+
tag = buf[used_length++];
/* blow out when we come to the end */
Index: slot.cpp
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/slot.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- slot.cpp 9 Dec 2009 01:55:15 -0000 1.13
+++ slot.cpp 8 Sep 2010 20:14:41 -0000 1.14
@@ -372,7 +372,7 @@
: log(log_), readerName(NULL), personName(NULL), manufacturer(NULL),
slotInfoFound(false), context(context_), conn(NULL), state(UNKNOWN),
isVersion1Key(false), needLogin(false), fullTokenName(false),
- mCoolkey(false),
+ mCoolkey(false), mOldCAC(false),
#ifdef USE_SHMEM
shmem(readerName_),
#endif
@@ -412,6 +412,9 @@
}
CKYBuffer_InitEmpty(&cardATR);
CKYBuffer_InitEmpty(&mCUID);
+ for (int i=0; i < MAX_CERT_SLOTS; i++) {
+ CKYBuffer_InitEmpty(&cardAID[i]);
+ }
} catch(PKCS11Exception &) {
if (conn) {
CKYCardConnection_Destroy(conn);
@@ -479,6 +482,9 @@
CKYBuffer_FreeData(&nonce);
CKYBuffer_FreeData(&cardATR);
CKYBuffer_FreeData(&mCUID);
+ for (int i=0; i < MAX_CERT_SLOTS; i++) {
+ CKYBuffer_FreeData(&cardAID[i]);
+ }
}
template <class C>
@@ -583,6 +589,7 @@
if( ! CKYCardConnection_IsConnected(conn) ) {
int i = 0;
//for cranky readers try again a few more times
+ status = CKYSCARDERR;
while( i++ < 5 && status != CKYSUCCESS )
{
status = CKYCardConnection_Connect(conn, readerName);
@@ -671,12 +678,12 @@
status = CKYApplet_SelectCoolKeyManager(conn, NULL);
if (status != CKYSUCCESS) {
log->log("CoolKey Select failed 0x%x\n", status);
- status = CACApplet_SelectPKI(conn, 0, NULL);
+ status = getCACAid();
if (status != CKYSUCCESS) {
- log->log("CAC Select failed 0x%x\n", status);
+ log->log("CAC Select failed 0x%x\n", status);
if (status == CKYSCARDERR) {
- log->log("CAC Card Failure 0x%x\n",
- CKYCardConnection_GetLastError(conn));
+ log->log("CAC Card Failure 0x%x\n",
+ CKYCardConnection_GetLastError(conn));
disconnect();
}
return;
@@ -689,6 +696,15 @@
isVersion1Key = 0;
needLogin = 1;
mCoolkey = 0;
+ return;
+loser:
+ log->log("CAC Select failed 0x%x\n", status);
+ if (status == CKYSCARDERR) {
+ log->log("CAC Card Failure 0x%x\n",
+ CKYCardConnection_GetLastError(conn));
+ disconnect();
+ }
+
return;
}
@@ -772,17 +788,111 @@
invalidateLogin(false);
}
+CKYStatus
+Slot::getCACAid()
+{
+ CKYBuffer tBuf;
+ CKYBuffer vBuf;
+ CKYSize tlen, vlen;
+ CKYOffset toffset, voffset;
+ int certSlot = 0;
+ int i,length = 0;
+ CKYStatus status;
+
+ CKYBuffer_InitEmpty(&tBuf);
+ CKYBuffer_InitEmpty(&vBuf);
+
+ /* clear out the card AID's */
+ for (i=0; i < MAX_CERT_SLOTS; i++) {
+ CKYBuffer_Resize(&cardAID[i],0);
+ }
+
+ status = CACApplet_SelectCCC(conn,NULL);
+ if (status != CKYSUCCESS) {
+ /* are we an old CAC */
+ status = CACApplet_SelectPKI(conn, &cardAID[0], 0, NULL);
+ if (status != CKYSUCCESS) {
+ /* no, just fail */
+ return status;
+ }
+ /* yes, fill in the old applets */
+ mOldCAC = true;
+ for (i=1; i< MAX_CERT_SLOTS; i++) {
+ CACApplet_SelectPKI(conn, &cardAID[i], i, NULL);
+ }
+ return CKYSUCCESS;
+ }
+ /* definately not an old CAC */
+ mOldCAC = false;
+
+ /* read the TLV */
+ status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ tlen = CKYBuffer_Size(&tBuf);
+ vlen = CKYBuffer_Size(&vBuf);
+
+ for(toffset = 2, voffset=2;
+ certSlot < MAX_CERT_SLOTS && toffset < tlen && voffset < vlen ;
+ voffset += length) {
+
+ CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset);
+ length = CKYBuffer_GetChar(&tBuf, toffset+1);
+ toffset += 2;
+ if (length == 0xff) {
+ length = CKYBuffer_GetShortLE(&tBuf, toffset);
+ toffset +=2;
+ }
+ if (tag != CAC_TAG_CARDURL) {
+ continue;
+ }
+ /* CARDURL tags must be at least 10 bytes long */
+ if (length < 10) {
+ continue;
+ }
+ /* check the app type, should be TLV_APP_PKI */
+ if (CKYBuffer_GetChar(&vBuf, voffset+5) != CAC_TLV_APP_PKI) {
+ continue;
+ }
+ status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf, voffset, 5);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf,
+ voffset+8, 2);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ cardEF[certSlot] = CKYBuffer_GetShortLE(&vBuf, voffset+6);
+
+ certSlot++;
+ }
+ status = CKYSUCCESS;
+ if (certSlot == 0) {
+ status = CKYAPDUFAIL; /* probably neeed a beter error code */
+ }
+
+done:
+ CKYBuffer_FreeData(&tBuf);
+ CKYBuffer_FreeData(&vBuf);
+ return status;
+}
+
void
Slot::refreshTokenState()
{
if( cardStateMayHaveChanged() ) {
-log->log("card changed\n");
+ log->log("card changed\n");
invalidateLogin(true);
closeAllSessions();
unloadObjects();
connectToToken();
-
if( state & APPLET_PERSONALIZED ) {
try {
loadObjects();
@@ -1020,7 +1130,7 @@
struct _manList {
unsigned short type;
- char *string;
+ const char *string;
};
static const struct _manList manList[] = {
@@ -1281,13 +1391,30 @@
Slot::selectCACApplet(CKYByte instance)
{
CKYStatus status;
- status = CACApplet_SelectPKI(conn, instance, NULL);
+ CKYBuffer *aid = &cardAID[instance];
+
+ if (CKYBuffer_Size(aid) == 0) {
+ disconnect();
+ throw PKCS11Exception(CKR_DEVICE_REMOVED);
+ return;
+ }
+
+ status = CKYApplet_SelectFile(conn, aid, NULL);
if ( status == CKYSCARDERR ) handleConnectionError();
if ( status != CKYSUCCESS) {
// could not select applet: this just means it's not there
disconnect();
throw PKCS11Exception(CKR_DEVICE_REMOVED);
}
+ if (mOldCAC) {
+ return;
+ }
+ status = CACApplet_SelectFile(conn, cardEF[instance], NULL);
+ if ( status == CKYSCARDERR ) handleConnectionError();
+ if ( status != CKYSUCCESS) {
+ disconnect();
+ throw PKCS11Exception(CKR_DEVICE_REMOVED);
+ }
}
// assume we are already in a transaction
void
@@ -2060,10 +2187,90 @@
return objInfoList;
}
+CKYStatus
+Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize,
+ bool throwException)
+{
+ CKYStatus status;
+ CKYISOStatus apduRC;
+ *nextSize = 0;
+
+ if (mOldCAC) {
+ /* get the first 100 bytes of the cert */
+ status = CACApplet_GetCertificateFirst(conn, cert, nextSize, &apduRC);
+ if (throwException && (status != CKYSUCCESS)) {
+ handleConnectionError();
+ }
+
+ if(CKYBuffer_Size(cert) == 0) {
+ handleConnectionError();
+ }
+ return status;
+ }
+
+ CKYBuffer tBuf;
+ CKYBuffer vBuf;
+ CKYSize tlen, vlen;
+ CKYOffset toffset, voffset;
+ int length = 0;
+
+ CKYBuffer_InitEmpty(&tBuf);
+ CKYBuffer_InitEmpty(&vBuf);
+ CKYBuffer_Resize(cert, 0);
+
+ /* handle the new CAC card read */
+ /* read the TLV */
+ status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL);
+ if (status != CKYSUCCESS) {
+ goto done;
+ }
+ tlen = CKYBuffer_Size(&tBuf);
+ vlen = CKYBuffer_Size(&vBuf);
+
+ /* look for the Cert out of the TLV */
+ for(toffset = 2, voffset=2; toffset < tlen && voffset < vlen ;
+ voffset += length) {
+
+ CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset);
+ length = CKYBuffer_GetChar(&tBuf, toffset+1);
+ toffset += 2;
+ if (length == 0xff) {
+ length = CKYBuffer_GetShortLE(&tBuf, toffset);
+ toffset +=2;
+ }
+ if (tag != CAC_TAG_CERTIFICATE) {
+ continue;
+ }
+ CKYBuffer_AppendBuffer(cert, &vBuf, voffset, length);
+ break;
+ }
+ status = CKYSUCCESS;
+
+done:
+ CKYBuffer_FreeData(&tBuf);
+ CKYBuffer_FreeData(&vBuf);
+ return status;
+}
+
+/*
+ * only necessary for old CAC cards. New CAC cards have to read the
+ * whole cert in anyway above....
+ */
+CKYStatus
+Slot::readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize)
+{
+ CKYISOStatus apduRC;
+ assert(mOldCAC);
+ return CACApplet_GetCertificateAppend(conn, cert, nextSize, &apduRC);
+}
+
void
Slot::loadCACCert(CKYByte instance)
{
- CKYISOStatus apduRC;
CKYStatus status = CKYSUCCESS;
CKYBuffer cert;
CKYBuffer rawCert;
@@ -2098,12 +2305,10 @@
instance, OSTimeNow() - time);
if (instance == 0) {
- /* get the first 100 bytes of the cert */
- status = CACApplet_GetCertificateFirst(conn, &rawCert,
- &nextSize, &apduRC);
- if (status != CKYSUCCESS) {
- handleConnectionError();
- }
+ readCACCertificateFirst(&rawCert, &nextSize, true);
+ if(CKYBuffer_Size(&rawCert) == 0) {
+ handleConnectionError();
+ }
log->log("CAC Cert %d: fetch CAC Cert: %d ms\n",
instance, OSTimeNow() - time);
}
@@ -2144,8 +2349,7 @@
shmem.setVersion(SHMEM_VERSION);
shmem.setDataVersion(dataVersion);
} else {
- status = CACApplet_GetCertificateFirst(conn, &rawCert,
- &nextSize, &apduRC);
+ status = readCACCertificateFirst(&rawCert, &nextSize, false);
if (status != CKYSUCCESS) {
/* CAC only requires the Certificate in pki '0' */
@@ -2160,8 +2364,7 @@
}
if (nextSize) {
- status = CACApplet_GetCertificateAppend(conn, &rawCert,
- nextSize, &apduRC);
+ status = readCACCertificateAppend(&rawCert, nextSize);
}
log->log("CAC Cert %d: Fetch rest : %d ms\n",
instance, OSTimeNow() - time);
@@ -2177,9 +2380,10 @@
log->log("CAC Cert %d: Cert has been read: %d ms\n",
instance, OSTimeNow() - time);
- if (CKYBuffer_GetChar(&rawCert,0) == 1) {
+ if (!mOldCAC || CKYBuffer_GetChar(&rawCert,0) == 1) {
CKYSize guessFinalSize = CKYBuffer_Size(&rawCert);
CKYSize certSize = 0;
+ CKYOffset offset = mOldCAC ? 1 : 0;
int zret = Z_MEM_ERROR;
do {
@@ -2190,7 +2394,8 @@
}
certSize = guessFinalSize;
zret = uncompress((Bytef *)CKYBuffer_Data(&cert),&certSize,
- CKYBuffer_Data(&rawCert)+1, CKYBuffer_Size(&rawCert)-1);
+ CKYBuffer_Data(&rawCert)+offset,
+ CKYBuffer_Size(&rawCert)-offset);
} while (zret == Z_BUF_ERROR);
if (zret != Z_OK) {
@@ -2527,7 +2732,7 @@
switch( result ) {
case CKYISO_SUCCESS:
break;
- case 6981:
+ case 0x6981:
throw PKCS11Exception(CKR_PIN_LOCKED);
default:
if ((result & 0xff00) == 0x6300) {
@@ -3206,6 +3411,10 @@
status = CKYApplet_ComputeCrypt(conn, keyNum, CKY_RSA_NO_PAD, direction,
input, NULL, output, getNonce(), &result);
}
+ /* map the ISO not logged in code to the coolkey one */
+ if (status == CKYISO_CONDITION_NOT_SATISFIED) {
+ status = (CKYStatus) CKYISO_UNAUTHORIZED;
+ }
if (status != CKYSUCCESS) {
if ( status == CKYSCARDERR ) {
handleConnectionError();
Index: slot.h
===================================================================
RCS file: /cvs/dirsec/coolkey/src/coolkey/slot.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- slot.h 19 Feb 2009 02:04:13 -0000 1.3
+++ slot.h 8 Sep 2010 20:14:41 -0000 1.4
@@ -294,6 +294,7 @@
const CKYBuffer *paddedOutput) const = 0;
};
+#define MAX_CERT_SLOTS 3
class Slot {
public:
@@ -328,6 +329,8 @@
CKYBuffer nonce;
CKYBuffer cardATR;
CKYBuffer mCUID;
+ CKYBuffer cardAID[MAX_CERT_SLOTS];
+ unsigned short cardEF[MAX_CERT_SLOTS];
bool isVersion1Key;
bool needLogin;
long publicFree;
@@ -335,6 +338,7 @@
long privateFree;
bool fullTokenName;
bool mCoolkey;
+ bool mOldCAC;
//enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
@@ -398,6 +402,11 @@
list<ListObjectInfo> fetchCombinedObjects(const CKYBuffer *header);
list<ListObjectInfo> fetchSeparateObjects();
+ CKYStatus getCACAid();
+ CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize,
+ bool throwException);
+ CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize);
+
void selectApplet();
void selectCACApplet(CKYByte instance);
void unloadObjects();
13 years, 7 months
coolkey/src/libckyapplet cky_applet.c, 1.2, 1.3 cky_applet.h, 1.2, 1.3 cky_base.c, 1.1, 1.2 cky_base.h, 1.1, 1.2 cky_factory.c, 1.2, 1.3 cky_factory.h, 1.2, 1.3
by Robert Relyea
Author: rrelyea
Update of /cvs/dirsec/coolkey/src/libckyapplet
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv6855/src/libckyapplet
Modified Files:
cky_applet.c cky_applet.h cky_base.c cky_base.h cky_factory.c
cky_factory.h
Log Message:
New CAC support
Index: cky_applet.c
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_applet.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cky_applet.c 19 Feb 2009 02:03:08 -0000 1.2
+++ cky_applet.c 8 Sep 2010 20:14:41 -0000 1.3
@@ -41,7 +41,13 @@
CKYStatus
CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
{
- return CKYAPDUFactory_SelectFile(apdu,(const CKYBuffer *)param);
+ return CKYAPDUFactory_SelectFile(apdu, 4, 0, (const CKYBuffer *)param);
+}
+
+CKYStatus
+CACAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
+{
+ return CKYAPDUFactory_SelectFile(apdu, 2, 12, (const CKYBuffer *)param);
}
CKYStatus
@@ -225,10 +231,17 @@
}
CKYStatus
-CACAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param)
+CACAppletFactory_SignDecryptStep(CKYAPDU *apdu, const void *param)
+{
+ const CKYBuffer *buf=(CKYBuffer *)param;
+ return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_STEP, buf);
+}
+
+CKYStatus
+CACAppletFactory_SignDecryptFinal(CKYAPDU *apdu, const void *param)
{
const CKYBuffer *buf=(CKYBuffer *)param;
- return CACAPDUFactory_SignDecrypt(apdu, buf);
+ return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_FINAL, buf);
}
CKYStatus
@@ -246,6 +259,13 @@
}
CKYStatus
+CACAppletFactory_ReadFile(CKYAPDU *apdu, const void *param)
+{
+ const CACAppletArgReadFile *rfs = (const CACAppletArgReadFile *)param;
+ return CACAPDUFactory_ReadFile(apdu, rfs->offset, rfs->type, rfs->count);
+}
+
+CKYStatus
CACAppletFactory_GetProperties(CKYAPDU *apdu, const void *param)
{
return CACAPDUFactory_GetProperties(apdu);
@@ -457,7 +477,7 @@
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL,
- 0, CKYAppletFill_Null, NULL, apduRC);
+ CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
}
static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 };
@@ -477,22 +497,23 @@
return ret;
}
-static CKYByte CACPKIid[] = {0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
+static CKYByte CACPKIid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01 };
/*
* Select the CoolKey applet. Must happen after we start a transaction and
* before we issue any applet specific command.
*/
CKYStatus
-CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
- CKYISOStatus *apduRC)
+CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cacAID,
+ CKYByte instance, CKYISOStatus *apduRC)
{
CKYStatus ret;
- CKYBuffer CACPKIAID;
- CKYBuffer_InitFromData(&CACPKIAID, CACPKIid, sizeof(CACPKIid));
- CKYBuffer_SetChar(&CACPKIAID, 6, instance);
- ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CACPKIAID,
+ CKYBuffer_AppendData(cacAID, CACPKIid, sizeof(CACPKIid));
+ CKYBuffer_AppendChar(cacAID, instance);
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, cacAID,
NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
- CKYBuffer_FreeData(&CACPKIAID);
+ if (ret != CKYSUCCESS) {
+ CKYBuffer_Resize(cacAID, 0);
+ }
return ret;
}
@@ -515,11 +536,38 @@
CKYBuffer CAC_CM_AID;
CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid));
ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
- NULL, 0, CKYAppletFill_Null, NULL, apduRC);
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
CKYBuffer_FreeData(&CAC_CM_AID);
return ret;
}
+static CKYByte cacCCCid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00 };
+CKYStatus
+CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer CAC_CM_AID;
+ CKYBuffer_InitFromData(&CAC_CM_AID, cacCCCid, sizeof(cacCCCid));
+ ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&CAC_CM_AID);
+ return ret;
+}
+
+CKYStatus
+CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYBuffer efBuf;
+ CKYBuffer_InitEmpty(&efBuf);
+ CKYBuffer_AppendShortLE(&efBuf, ef);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SelectFile, &efBuf,
+ NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
+ CKYBuffer_FreeData(&efBuf);
+ return ret;
+}
+
/*
* GetCPLC cluster -- must be called with CM selected
*/
@@ -673,8 +721,8 @@
ccd.keyNumber = keyNumber;
ccd.location = location;
ccd.data = data;
- return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, &ccd,
- nonce, 0, CKYAppletFill_Null, NULL, apduRC);
+ return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess,
+ &ccd, nonce, 0, CKYAppletFill_Null, NULL, apduRC);
}
/* computeCrypt returns data in the form :
@@ -832,11 +880,39 @@
CKYBuffer *result, CKYISOStatus *apduRC)
{
CKYStatus ret;
-
- ret = CKYApplet_HandleAPDU(conn,
- CACAppletFactory_SignDecrypt, data, NULL,
- CKYBuffer_Size(data), CKYAppletFill_ReplaceBuffer,
+ CKYSize dataSize = CKYBuffer_Size(data);
+ CKYOffset offset = 0;
+ CKYBuffer tmp;
+
+ CKYBuffer_InitEmpty(&tmp);
+
+ CKYBuffer_Resize(result, 0);
+ for(offset = 0; (dataSize-offset) > CKY_MAX_WRITE_CHUNK_SIZE;
+ offset += CKY_MAX_WRITE_CHUNK_SIZE) {
+ CKYBuffer_Resize(&tmp,0);
+ CKYBuffer_AppendBuffer(&tmp, data, offset, CKY_MAX_WRITE_CHUNK_SIZE);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptStep,
+ &tmp, NULL, CKY_SIZE_UNKNOWN,
+ CKYAppletFill_AppendBuffer,
result, apduRC);
+ if (ret != CKYSUCCESS) {
+ goto done;
+ }
+ }
+ CKYBuffer_Resize(&tmp,0);
+ CKYBuffer_AppendBuffer(&tmp, data, offset, dataSize - offset);
+ ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptFinal,
+ &tmp, NULL, CKY_SIZE_UNKNOWN,
+ CKYAppletFill_AppendBuffer,
+ result, apduRC);
+
+ if ((ret == CKYSUCCESS) && (CKYBuffer_Size(result) != dataSize)) {
+ /* RSA returns the same data size as input, didn't happen, so
+ * something is wrong. */
+ }
+
+done:
+ CKYBuffer_FreeData(&tmp);
return ret;
}
@@ -895,6 +971,63 @@
}
return ret;
}
+
+/*
+ * Read a CAC Tag/Value file
+ */
+CKYStatus
+CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type, CKYBuffer *buffer,
+ CKYISOStatus *apduRC)
+{
+ CKYStatus ret;
+ CKYISOStatus status;
+ CKYByte maxtransfer;
+ unsigned short offset = 0;
+ unsigned short size;
+ CACAppletArgReadFile rfs;
+
+ CKYBuffer_Resize(buffer,0);
+ if (apduRC == NULL) {
+ apduRC = &status;
+ }
+ rfs.offset = 0;
+ rfs.count = 2;
+ rfs.type = type;
+
+ /* APDU's are expensive, Grab a big chunk of the file first if possible */
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_ReadFile, &rfs, NULL,
+ rfs.count, CKYAppletFill_AppendBuffer,
+ buffer, apduRC);
+ /* file is probably smaller than 100 bytes, get the actual size first */
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ size = CKYBuffer_GetShortLE(buffer, 0) + 2 /* include the length itself */;
+ maxtransfer = CKY_MAX_READ_CHUNK_SIZE;
+ /* get the rest of the buffer if necessary */
+ for (offset = CKYBuffer_Size(buffer); size > offset;
+ offset = CKYBuffer_Size(buffer)) {
+ rfs.offset = offset;
+ rfs.count = MIN(size - offset, maxtransfer);
+ ret = CKYApplet_HandleAPDU(conn,
+ CACAppletFactory_ReadFile, &rfs, NULL,
+ rfs.count, CKYAppletFill_AppendBuffer,
+ buffer, apduRC);
+ if (ret != CKYSUCCESS) {
+ if (*apduRC == CAC_INVALID_PARAMS) {
+ maxtransfer = maxtransfer/2;
+ if (maxtransfer == 0) {
+ return ret;
+ }
+ } else {
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
CKYStatus
CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert,
CKYSize *nextSize, CKYISOStatus *apduRC)
Index: cky_applet.h
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_applet.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cky_applet.h 19 Feb 2009 02:03:08 -0000 1.2
+++ cky_applet.h 8 Sep 2010 20:14:41 -0000 1.3
@@ -43,6 +43,7 @@
#define CKYISO_MORE_MASK 0xff00 /* More data mask */
#define CKYISO_MORE 0x6300 /* More data available */
#define CKYISO_DATA_INVALID 0x6984
+#define CKYISO_CONDITION_NOT_SATISFIED 0x6985 /* AKA not logged in */
/* Applet Defined Return codes */
#define CKYISO_NO_MEMORY_LEFT 0x9c01 /* There have been memory
* problems on the card */
@@ -71,6 +72,15 @@
#define CKYISO_INTERNAL_ERROR 0x9cff /* Reserved for debugging,
* shouldn't happen */
+#define CAC_INVALID_PARAMS 0x6a83
+#define CAC_TAG_FILE 1
+#define CAC_VALUE_FILE 2
+
+
+#define CAC_TAG_CARDURL 0xf3
+#define CAC_TAG_CERTIFICATE 0x70
+#define CAC_TLV_APP_PKI 0x04
+
/*
* Pin Constants as used by our applet
*/
@@ -209,6 +219,12 @@
const CKYBuffer *sig;
} CKYAppletArgComputeCrypt;
+typedef struct _CACAppletArgReadFile {
+ CKYByte type;
+ CKYByte count;
+ unsigned short offset;
+} CACAppletArgReadFile;
+
/* fills in an APDU from a structure -- form of all the generic factories*/
typedef CKYStatus (*CKYAppletFactory)(CKYAPDU *apdu, const void *param);
/* fills in an a structure from a response -- form of all the fill structures*/
@@ -451,9 +467,17 @@
/* Select the CAC card manager. Can happen with either applet selected */
CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn,
CKYISOStatus *apduRC);
-/* Can happen with either applet selected */
-CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
- CKYISOStatus *apduRC);
+/* Select the CAC CC container. Can happen with either applet selected */
+CKYStatus CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC);
+/* Select an old CAC applet and fill in the cardAID */
+CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cardAid,
+ CKYByte instance, CKYISOStatus *apduRC);
+/* read a TLV file */
+CKYStatus CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type,
+ CKYBuffer *buffer, CKYISOStatus *apduRC);
+CKYStatus CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
+ CKYISOStatus *apduRC);
+
/* must happen with PKI applet selected */
CKYStatus CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
CKYBuffer *result, CKYISOStatus *apduRC);
Index: cky_base.c
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_base.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- cky_base.c 9 Jun 2006 18:44:17 -0000 1.1
+++ cky_base.c 8 Sep 2010 20:14:41 -0000 1.2
@@ -220,6 +220,22 @@
return CKYSUCCESS;
}
+/* append a short in network order */
+CKYStatus
+CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 2;
+ return CKYSUCCESS;
+}
+
/* append a long in applet order */
CKYStatus
CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val)
@@ -238,6 +254,24 @@
return CKYSUCCESS;
}
+/* append a long in applet order */
+CKYStatus
+CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val)
+{
+ CKYStatus ret;
+
+ ret = CKYBuffer_Reserve(buf, buf->len + 4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ buf->data[buf->len+3] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[buf->len+2] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
+ buf->len += 4;
+ return CKYSUCCESS;
+}
+
CKYStatus
CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data, CKYSize len)
{
@@ -351,6 +385,22 @@
}
CKYStatus
+CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+2) {
+ ret = CKYBuffer_Resize(buf,offset+2);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
+CKYStatus
CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val)
{
CKYStatus ret;
@@ -368,6 +418,24 @@
return CKYSUCCESS;
}
+CKYStatus
+CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val)
+{
+ CKYStatus ret;
+
+ if (buf->len < offset+4) {
+ ret = CKYBuffer_Resize(buf,offset+4);
+ if (ret != CKYSUCCESS) {
+ return ret;
+ }
+ }
+ buf->data[offset+3] = (CKYByte) ((val >> 24) & 0xff);
+ buf->data[offset+2] = (CKYByte) ((val >> 16) & 0xff);
+ buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
+ buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
+ return CKYSUCCESS;
+}
+
CKYByte
CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset)
{
@@ -388,6 +456,18 @@
val |= ((unsigned short)buf->data[offset+1]) << 0;
return val;
}
+
+unsigned short
+CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned short val;
+ if (buf->len < offset+2) {
+ return 0;
+ }
+ val = ((unsigned short)buf->data[offset+1]) << 8;
+ val |= ((unsigned short)buf->data[offset+0]) << 0;
+ return val;
+}
unsigned long
CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset)
@@ -402,6 +482,20 @@
val |= ((unsigned long)buf->data[offset+3]) << 0;
return val;
}
+
+unsigned long
+CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset)
+{
+ unsigned long val;
+ if (buf->len < offset+4) {
+ return 0;
+ }
+ val = ((unsigned long)buf->data[offset+3]) << 24;
+ val |= ((unsigned long)buf->data[offset+2]) << 16;
+ val |= ((unsigned long)buf->data[offset+1]) << 8;
+ val |= ((unsigned long)buf->data[offset+0]) << 0;
+ return val;
+}
CKYStatus
CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen)
Index: cky_base.h
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_base.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- cky_base.h 9 Jun 2006 18:44:17 -0000 1.1
+++ cky_base.h 8 Sep 2010 20:14:41 -0000 1.2
@@ -170,9 +170,15 @@
/* append a short in applet order */
CKYStatus CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val);
+/* append a short in little endian order */
+CKYStatus CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val);
+
/* append a long in applet order */
CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val);
+/* append a long in little endian order */
+CKYStatus CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val);
+
/* append data. the data starts at data and extends len bytes */
CKYStatus CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
@@ -210,12 +216,18 @@
CKYStatus CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val);
CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val);
+/* These functions work in little endian order */
+CKYStatus CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val);
+CKYStatus CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val);
/* read a character from offset. If offset is beyond the end of the buffer,
* then the function returns '0' */
CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset);
/* These functions work in applet order */
unsigned short CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset);
unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset);
+/* These functions work in little endian order */
+unsigned short CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset);
+unsigned long CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset);
/* clear out all the data in a buffer */
void CKYBuffer_Zero(CKYBuffer *buf);
Index: cky_factory.c
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_factory.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cky_factory.c 19 Feb 2009 02:03:08 -0000 1.2
+++ cky_factory.c 8 Sep 2010 20:14:41 -0000 1.3
@@ -25,12 +25,13 @@
* special commands can be issued at any time
*/
CKYStatus
-CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID)
+CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
+ const CKYBuffer *AID)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE);
- CKYAPDU_SetP1(apdu, 0x04);
- CKYAPDU_SetP2(apdu, 0x00);
+ CKYAPDU_SetP1(apdu, p1);
+ CKYAPDU_SetP2(apdu, p2);
return CKYAPDU_SetSendDataBuffer(apdu, AID);
}
@@ -131,6 +132,7 @@
return ret;
}
+
CKYStatus
CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, const CKYBuffer *sig)
@@ -572,11 +574,11 @@
}
CKYStatus
-CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data)
+CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, const CKYBuffer *data)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CAC_INS_SIGN_DECRYPT);
- CKYAPDU_SetP1(apdu, 0x00);
+ CKYAPDU_SetP1(apdu, type);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetSendDataBuffer(apdu, data);
}
@@ -592,6 +594,36 @@
}
CKYStatus
+CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
+ CKYByte type, CKYByte count)
+{
+ CKYStatus ret;
+ CKYBuffer buf;
+
+ CKYBuffer_InitEmpty(&buf);
+ CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM);
+ CKYAPDU_SetINS(apdu, CAC_INS_READ_FILE);
+ CKYAPDU_SetP1(apdu, (offset >> 8) & 0xff);
+ CKYAPDU_SetP2(apdu, offset & 0xff);
+ ret = CKYBuffer_Reserve(&buf, 2);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, type);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYBuffer_AppendChar(&buf, count);
+ if (ret != CKYSUCCESS) {
+ goto fail;
+ }
+ ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
+fail:
+ CKYBuffer_FreeData(&buf);
+ return ret;
+}
+
+CKYStatus
CACAPDUFactory_GetProperties(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
Index: cky_factory.h
===================================================================
RCS file: /cvs/dirsec/coolkey/src/libckyapplet/cky_factory.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- cky_factory.h 19 Feb 2009 02:03:08 -0000 1.2
+++ cky_factory.h 8 Sep 2010 20:14:41 -0000 1.3
@@ -86,7 +86,11 @@
#define CAC_INS_SIGN_DECRYPT 0x42
#define CAC_INS_VERIFY_PIN 0x20
#define CAC_INS_GET_PROPERTIES 0x56
+#define CAC_INS_READ_FILE 0x52
+
#define CAC_SIZE_GET_PROPERTIES 48
+#define CAC_P1_STEP 0x80
+#define CAC_P1_FINAL 0x00
/*
* Fixed return sized from various commands
@@ -169,7 +173,8 @@
CKY_BEGIN_PROTOS
/* function based factorys */
-CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID);
+CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
+ const CKYBuffer *AID);
CKYStatus CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence);
@@ -211,9 +216,12 @@
CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu);
-CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data);
+CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type,
+ const CKYBuffer *data);
CKYStatus CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin);
CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size);
+CKYStatus CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
+ CKYByte type, CKYByte count);
CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu);
CKY_END_PROTOS
13 years, 7 months
5 commits - ldap/servers
by Nathan Kinder
ldap/servers/plugins/dna/dna.c | 5 ++++-
ldap/servers/plugins/replication/windows_connection.c | 17 +++++++++++++++--
ldap/servers/slapd/back-ldbm/id2entry.c | 7 ++++++-
ldap/servers/slapd/back-ldbm/idl_new.c | 15 +++++++++++++--
ldap/servers/slapd/protect_db.c | 9 +++++----
ldap/servers/slapd/protect_db.h | 3 +++
6 files changed, 46 insertions(+), 10 deletions(-)
New commits:
commit b2962bd5ecab66571b2afe223a61ff1a7d53dc3c
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 10:47:07 2010 -0700
Bug 630096 - (cov#15447) - Check return value of idl_append_extend()
We should check the return type of idl_append_extend(), though it does
not seem possible that the return type will be anything other than 0.
The only time idl_append_extend() returns anything other than 0 is
when it is unable to allocate memory. Since the underlying allocation
function is slapi_ch_calloc(), the server will just exit if it runs
out of memory, which means we will never return up through
idl_append_extend(). The right thing to do from a code standpoint is
to still check for the return value though.
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
index 20eee68..298d5e8 100644
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
@@ -154,6 +154,7 @@ IDList * idl_new_fetch(
)
{
int ret = 0;
+ int idl_rc = 0;
DBC *cursor = NULL;
IDList *idl = NULL;
DBT key;
@@ -246,7 +247,12 @@ IDList * idl_new_fetch(
memcpy(&id, dataret.data, sizeof(ID));
/* we got another ID, add it to our IDL */
- idl_append_extend(&idl, id);
+ idl_rc = idl_append_extend(&idl, id);
+ if (idl_rc) {
+ LDAPDebug(LDAP_DEBUG_ANY, "unable to extend id list (err=%d)\n", idl_rc, 0, 0);
+ idl_free(idl); idl = NULL;
+ goto error;
+ }
count++;
}
@@ -275,7 +281,12 @@ IDList * idl_new_fetch(
break;
}
/* we got another ID, add it to our IDL */
- idl_append_extend(&idl, id);
+ idl_rc = idl_append_extend(&idl, id);
+ if (idl_rc) {
+ LDAPDebug(LDAP_DEBUG_ANY, "unable to extend id list (err=%d)\n", idl_rc);
+ idl_free(idl); idl = NULL;
+ goto error;
+ }
#if defined(DB_ALLIDS_ON_READ)
/* enforce the allids read limit */
if (count > idl_new_get_allidslimit(a)) {
commit 3835f3ccd452c8d8af26f54ac04433f9f581a2ff
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 10:33:23 2010 -0700
Bug 630096 - (cov#15448) Check return value of cache_replace()
We need to check the return value of cache_replace() in
id2entry_add_ext(). The only possible error that can be returned
is when the entry we are trying to replace is not found in the
cache. This should not occur since we are told that the entry
already exists by CACHE_ADD() just prior to this call. If we run
into this situation, we will just log an error without adding the
entry to the cache. This shouldn't be a big deal since the entry
will get added to the cache next time it is accessed.
diff --git a/ldap/servers/slapd/back-ldbm/id2entry.c b/ldap/servers/slapd/back-ldbm/id2entry.c
index 15d742c..198fdd5 100644
--- a/ldap/servers/slapd/back-ldbm/id2entry.c
+++ b/ldap/servers/slapd/back-ldbm/id2entry.c
@@ -104,7 +104,12 @@ id2entry_add_ext( backend *be, struct backentry *e, back_txn *txn, int encrypt
* replace it. */
if (CACHE_ADD( &inst->inst_dncache, bdn, &oldbdn ) == 1) {
if (slapi_sdn_compare(sdn, oldbdn->dn_sdn)) {
- cache_replace( &inst->inst_dncache, oldbdn, bdn );
+ if (cache_replace( &inst->inst_dncache, oldbdn, bdn ) != 0) {
+ /* The entry was not in the cache for some reason (this
+ * should not happen since CACHE_ADD said it existed above). */
+ LDAPDebug( LDAP_DEBUG_ANY, "id2entry_add_ext(): Entry disappeared "
+ "from cache (%s)\n", oldbdn->dn_sdn, 0, 0 );
+ }
}
CACHE_RETURN(&inst->inst_dncache, &oldbdn); /* to free oldbdn */
}
commit a333e683d6b15eafb5a098e581eb7a281b15137c
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 07:58:15 2010 -0700
Bug 630096 - (cov#15449,15450) Check return value of stat()
We were not checking the return value of stat() before attempting
to access the structure that stat fille in in the protect_db code.
This patch checks the return value first.
diff --git a/ldap/servers/slapd/protect_db.c b/ldap/servers/slapd/protect_db.c
index c90c800..ce11394 100644
--- a/ldap/servers/slapd/protect_db.c
+++ b/ldap/servers/slapd/protect_db.c
@@ -205,10 +205,12 @@ make_sure_dir_exists(char *dir)
slapdFrontendConfig->localuserinfo != NULL) {
pw = slapdFrontendConfig->localuserinfo;
if (chown(dir, pw->pw_uid, -1) == -1) {
- stat(dir, &stat_buffer);
- if (stat_buffer.st_uid != pw->pw_uid) {
+ if ((stat(dir, &stat_buffer) == 0) && (stat_buffer.st_uid != pw->pw_uid)) {
LDAPDebug(LDAP_DEBUG_ANY, CHOWN_WARNING, dir, 0, 0);
return 1;
+ } else {
+ LDAPDebug(LDAP_DEBUG_ANY, STAT_ERROR, dir, errno, 0);
+ return 1;
}
}
}
@@ -242,8 +244,7 @@ add_this_process_to(char *dir_name)
slapdFrontendConfig->localuserinfo != NULL) {
pw = slapdFrontendConfig->localuserinfo;
if (chown(file_name, pw->pw_uid, -1) == -1) {
- stat(file_name, &stat_buffer);
- if (stat_buffer.st_uid != pw->pw_uid) {
+ if ((stat(file_name, &stat_buffer) == 0) && (stat_buffer.st_uid != pw->pw_uid)) {
LDAPDebug(LDAP_DEBUG_ANY, CHOWN_WARNING, file_name, 0, 0);
}
}
diff --git a/ldap/servers/slapd/protect_db.h b/ldap/servers/slapd/protect_db.h
index 1def34c..bbb5324 100644
--- a/ldap/servers/slapd/protect_db.h
+++ b/ldap/servers/slapd/protect_db.h
@@ -76,6 +76,9 @@ void remove_slapd_process();
#define CHOWN_WARNING "Warning - couldn't set the ownership for %s\n"
/* file name */
+#define STAT_ERROR "Error - unable to stat %s (error %d)\n"
+ /* file name, error number */
+
#define NO_SERVER_DUE_TO_SERVER "Unable to start slapd because it is already running as process %d\n"
/* pid of running slapd process */
commit a733cd11e91d956242452ba4dd1d37406bec4aa4
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Sep 3 14:04:16 2010 -0700
Bug 630096 - (cov#15446) check return value of ber_scanf()
We were not checking the return value of ber_scanf in the DNA
plug-in when parsing the range transfer response. This checks
the return value and sets the return code to LDAP_PROTOCOL_ERROR
if we were unable to parse the range transfer response.
diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c
index 558e613..837b674 100644
--- a/ldap/servers/plugins/dna/dna.c
+++ b/ldap/servers/plugins/dna/dna.c
@@ -1604,7 +1604,10 @@ static int dna_request_range(struct configEntry *config_entry,
/* Parse response */
if (responsedata) {
respber = ber_init(responsedata);
- ber_scanf(respber, "{aa}", &lower_str, &upper_str);
+ if (ber_scanf(respber, "{aa}", &lower_str, &upper_str) == LBER_ERROR) {
+ ret = LDAP_PROTOCOL_ERROR;
+ goto bail;
+ }
}
/* Fill in upper and lower */
commit eed34c50e31a1b62a8185096cdbc3d7763125f3a
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 10:31:22 2010 -0700
Bug 630096 - (cov#11778) check return value of ldap_parse_result
We were not checking the return value of ldap_parse_result in the
windows_check_user_password() function. The old code was a bit
unclear about setting rc when we encountered errors from
ldap_result(). It also was calling ldap_parse_result() even if
ldap_result() encountered an error. I fixed this code to be a
bit more straightforward.
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index f337b94..8685f3c 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -1808,7 +1808,8 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
}
/* Attempt to bind as a user to AD in order to see if we posess the
- * most current password. Returns the LDAP return code of the bind. */
+ * most current password. Returns 0 if the bind was successful,
+ * non-zero otherwise. */
int
windows_check_user_password(Repl_Connection *conn, Slapi_DN *sdn, char *password)
{
@@ -1816,6 +1817,7 @@ windows_check_user_password(Repl_Connection *conn, Slapi_DN *sdn, char *password
LDAPMessage *res = NULL;
int rc = 0;
int msgid = 0;
+ int parse_rc = 0;
/* If we're already connected, this will just return success */
windows_conn_connect(conn);
@@ -1839,8 +1841,19 @@ windows_check_user_password(Repl_Connection *conn, Slapi_DN *sdn, char *password
"Error: timeout reading "
"bind response for [%s]\n",
binddn ? binddn : "(anon)");
+ rc = -1;
+ } else {
+ parse_rc = ldap_parse_result( conn->ld, res, &rc, NULL, NULL, NULL, NULL, 1 /* Free res */);
+ if (parse_rc != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "Error: unable to parse "
+ "bind result for [%s]: "
+ "error %d\n",
+ binddn ? binddn : "(anon)",
+ parse_rc);
+ rc = -1;
+ }
}
- ldap_parse_result( conn->ld, res, &rc, NULL, NULL, NULL, NULL, 1 /* Free res */);
/* rebind as the DN specified in the sync agreement */
bind_and_check_pwp(conn, conn->binddn, conn->plain);
13 years, 7 months
2 commits - ldap/servers
by Nathan Kinder
ldap/servers/plugins/referint/referint.c | 127 +++++++++++++++----------------
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 7 -
2 files changed, 66 insertions(+), 68 deletions(-)
New commits:
commit cd99e197f22f7a26fae930d72b507a92e06313a8
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 09:51:21 2010 -0700
Bug 630093 - (cov#15518) Need to intialize fd in ldbm2ldif code
Currently, the ldbm_back_ldbm2ldif() function could bail due to an
error before fd is set. We then attempt to close the file that fd
refers to. We should initialize fd to STDOUT_FILENUM, as we skip
calling close() if fd is set to STDOUT_FILENUM.
Additionally, I noticed that we could call close() when fd is
negative or if it is STDERR or STDIN. I fixed this so close() is
not called in those cases.
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index 1b7b7ae..f1b50ae 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -885,7 +885,6 @@ static IDList *ldbm_fetch_subtrees(backend *be, char **include, int *err)
return idltotal;
}
-#define FD_STDOUT 1
static int
export_one_entry(struct ldbminfo *li,
@@ -999,7 +998,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb )
int decrypt = 0;
int dump_replica = 0;
int dump_uniqueid = 1;
- int fd;
+ int fd = STDOUT_FILENO;
IDList *idl = NULL; /* optimization for -s include lists */
int cnt = 0, lastcnt = 0;
int options = 0;
@@ -1168,7 +1167,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb )
goto bye;
}
} else { /* '-' */
- fd = FD_STDOUT;
+ fd = STDOUT_FILENO;
}
if ( we_start_the_backends ) {
@@ -1516,7 +1515,7 @@ bye:
dblayer_release_id2entry( be, db );
- if (fd != FD_STDOUT) {
+ if (fd > STDERR_FILENO) {
close(fd);
}
commit 57edbb0f52649d2d4c643b58da360619ae078b7d
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Wed Sep 8 08:28:37 2010 -0700
Bug 630093 - (cov#15511) Don't use unintialized search_results in refint plugin
The refint plug-in code currently looks as if it could use the
search_result variable when it is uninitialized. I don't believe
that this is possible since it would require the filter variable
to be NULL, which should not occur since slapi_ch_smprintf() would
make the process exit if it failed to allocate memory. Even so,
the correct thing to do from a code cleanliness standpoint is to
move all code that assumes we performed a search into the "if (filter)"
block.
diff --git a/ldap/servers/plugins/referint/referint.c b/ldap/servers/plugins/referint/referint.c
index 3207e5b..3ef9de6 100644
--- a/ldap/servers/plugins/referint/referint.c
+++ b/ldap/servers/plugins/referint/referint.c
@@ -690,7 +690,6 @@ update_integrity(char **argv, char *origDN,
size_t len = strlen(origDN);
filter = slapi_ch_smprintf("(%s=*%s)", argv[i], escape_filter_value(origDN, len, buf));
if ( filter ) {
-
/* Need only the current attribute and its subtypes */
char *attrs[2];
attrs[0] = argv[i];
@@ -705,79 +704,79 @@ update_integrity(char **argv, char *origDN,
slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT,
&search_result);
- }
-
- /* if search successfull then do integrity update */
- if(search_result == LDAP_SUCCESS)
- {
- slapi_pblock_get(search_result_pb,
- SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &search_entries);
- for(j=0; search_entries[j] != NULL; j++)
+ /* if search successfull then do integrity update */
+ if(search_result == LDAP_SUCCESS)
{
- Slapi_Attr *attr = NULL;
- char *attrName = NULL;
+ slapi_pblock_get(search_result_pb,
+ SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
+ &search_entries);
- /* Loop over all the attributes of the entry and search
- * for the integrity attribute and its subtypes */
- for (slapi_entry_first_attr(search_entries[j], &attr); attr;
- slapi_entry_next_attr(search_entries[j], attr, &attr))
+ for(j=0; search_entries[j] != NULL; j++)
{
- /* Take into account only the subtypes of the attribute
- * in argv[i] having the necessary value - origDN */
- slapi_attr_get_type(attr, &attrName);
- if (slapi_attr_type_cmp(argv[i], attrName,
- SLAPI_TYPE_CMP_SUBTYPE) == 0)
+ Slapi_Attr *attr = NULL;
+ char *attrName = NULL;
+
+ /* Loop over all the attributes of the entry and search
+ * for the integrity attribute and its subtypes */
+ for (slapi_entry_first_attr(search_entries[j], &attr); attr;
+ slapi_entry_next_attr(search_entries[j], attr, &attr))
{
- int nval = 0;
- slapi_attr_get_numvalues(attr, &nval);
-
- /*
- * We want to reduce the "modify" call as much as
- * possible. But if an entry contains 1000s of
- * attributes which need to be updated by the
- * referint plugin (e.g., a group containing 1000s
- * of members), we want to avoid to allocate too
- * many mods * in one "modify" call.
- * This is a compromise: If an attribute type has
- * more than 128 values, we update the attribute
- * value one by one. Otherwise, update all values
- * in one "modify" call.
- */
- if (nval > 128) {
- rc = _update_one_per_mod(
- slapi_entry_get_dn(search_entries[j]),
- attr, attrName,
- origDN, norm_origDN,
- newrDN, newsuperior,
- mod_pb);
- } else {
- rc = _update_all_per_mod(
- slapi_entry_get_dn(search_entries[j]),
- attr, attrName,
- origDN, norm_origDN,
- newrDN, newsuperior,
- mod_pb);
+ /* Take into account only the subtypes of the attribute
+ * in argv[i] having the necessary value - origDN */
+ slapi_attr_get_type(attr, &attrName);
+ if (slapi_attr_type_cmp(argv[i], attrName,
+ SLAPI_TYPE_CMP_SUBTYPE) == 0)
+ {
+ int nval = 0;
+ slapi_attr_get_numvalues(attr, &nval);
+
+ /*
+ * We want to reduce the "modify" call as much as
+ * possible. But if an entry contains 1000s of
+ * attributes which need to be updated by the
+ * referint plugin (e.g., a group containing 1000s
+ * of members), we want to avoid to allocate too
+ * many mods * in one "modify" call.
+ * This is a compromise: If an attribute type has
+ * more than 128 values, we update the attribute
+ * value one by one. Otherwise, update all values
+ * in one "modify" call.
+ */
+ if (nval > 128) {
+ rc = _update_one_per_mod(
+ slapi_entry_get_dn(search_entries[j]),
+ attr, attrName,
+ origDN, norm_origDN,
+ newrDN, newsuperior,
+ mod_pb);
+ } else {
+ rc = _update_all_per_mod(
+ slapi_entry_get_dn(search_entries[j]),
+ attr, attrName,
+ origDN, norm_origDN,
+ newrDN, newsuperior,
+ mod_pb);
+ }
+ /* Should we stop if one modify returns an error? */
}
- /* Should we stop if one modify returns an error? */
}
}
+ } else {
+ if (isFatalSearchError(search_result))
+ {
+ /* NPCTE fix for bugid 531225, esc 0. <P.R> <30-May-2001> */
+ slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
+ "update_integrity search (base=%s filter=%s) returned "
+ "error %d\n", search_base, filter, search_result);
+ /* end of NPCTE fix for bugid 531225 */
+ rc = -1;
+ goto free_and_return;
+ }
}
- } else {
- if (isFatalSearchError(search_result))
- {
- /* NPCTE fix for bugid 531225, esc 0. <P.R> <30-May-2001> */
- slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM,
- "update_integrity search (base=%s filter=%s) returned "
- "error %d\n", search_base, filter, search_result);
- /* end of NPCTE fix for bugid 531225 */
- rc = -1;
- goto free_and_return;
- }
- }
- slapi_ch_free_string(&filter);
+ slapi_ch_free_string(&filter);
+ }
if (search_result_pb) {
slapi_free_search_results_internal(search_result_pb);
13 years, 7 months
ldap/servers
by Richard Allen Megginson
ldap/servers/slapd/ldaputil.c | 5 +++++
1 file changed, 5 insertions(+)
New commits:
commit 44e10f3486e46d4d940dc5bad85aaf786805eb06
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Fri Sep 3 11:27:39 2010 -0600
Have to explicitly set protocol version to 3
openldap requires that the protocol version be explicitly set to 3
mozldap defaults to 3, but it doesn't hurt to set it again
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 77b08cd..3d65efc 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -593,6 +593,7 @@ slapi_ldap_init_ext(
LDAP *ld = NULL;
int rc = 0;
int secureurl = 0;
+ int ldap_version3 = LDAP_VERSION3;
/* We need to provide a sasl path used for client connections, especially
if the server is not set up to be a sasl server - since mozldap provides
@@ -723,6 +724,10 @@ slapi_ldap_init_ext(
ld = prldap_init(hostname, port, shared);
}
#endif /* !USE_OPENLDAP */
+
+ /* must explicitly set version to 3 */
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version3);
+
/* Update snmp interaction table */
if (hostname) {
if (ld == NULL) {
13 years, 7 months
ldap/servers
by Nathan Kinder
ldap/servers/slapd/back-ldbm/cache.c | 2 --
1 file changed, 2 deletions(-)
New commits:
commit 644b5531bc27c0813298c79c3f1affd50dc40dbf
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Sep 3 11:22:31 2010 -0700
Bug 630098 - fix coverity Defect Type: Code maintainability issues
(cov#15521) The oldndn variable was unused in the dncache_replace() function.
This patch removes the unused variable.
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 120a14a..721a838 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1736,7 +1736,6 @@ static int
dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
{
int found;
- const char *oldndn;
if (!entryrdn_get_switch()) {
return 0;
@@ -1749,7 +1748,6 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
* where the entry isn't in all the table yet, so we don't care if any
* of these return errors.
*/
- oldndn = slapi_sdn_get_ndn(olddn->dn_sdn);
PR_Lock(cache->c_mutex);
/*
13 years, 7 months
ldap/servers
by Nathan Kinder
ldap/servers/slapd/back-ldbm/cache.c | 2 --
1 file changed, 2 deletions(-)
New commits:
commit 8eddca4e52a9a00eb4ff1b4e868d19319d69d4d6
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Sep 3 10:46:26 2010 -0700
Bug 630098 - fix coverity Defect Type: Code maintainability issues
(cov#15521) The newndn variable was unused in the dncache_replace() function.
This patch removes the unused variable.
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index be45ddc..120a14a 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1737,7 +1737,6 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
{
int found;
const char *oldndn;
- const char *newndn;
if (!entryrdn_get_switch()) {
return 0;
@@ -1751,7 +1750,6 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
* of these return errors.
*/
oldndn = slapi_sdn_get_ndn(olddn->dn_sdn);
- newndn = slapi_sdn_get_ndn(newdn->dn_sdn);
PR_Lock(cache->c_mutex);
/*
13 years, 7 months
ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/usn/usn.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit 3c4185bb9fad50b44dc86b961d2e85535afe5e56
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu Sep 2 12:06:25 2010 -0600
use slapi_mods_init_passin/get_ldapmods_passout if modifying the smods
When using slapi_mods_init_byref/get_ldapmods_byref, the slapi_mods code
expects the Slapi_Mods to be read-only. Since the usn code adds a mod
to the list, it needs to use the slapi_mods_init_passin/get_ldapmods_passout
APIs. This avoids an assertion when using --enable-debug.
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
index 5dd5122..914c7ac 100644
--- a/ldap/servers/plugins/usn/usn.c
+++ b/ldap/servers/plugins/usn/usn.c
@@ -374,12 +374,12 @@ _usn_mod_next_usn(LDAPMod ***mods, Slapi_Backend *be)
bvals[0] = &usn_berval;
bvals[1] = NULL;
- slapi_mods_init_byref(&smods, *mods);
+ slapi_mods_init_passin(&smods, *mods);
/* bvals is duplicated by ber_bvdup in slapi_mods_add_modbvps */
slapi_mods_add_modbvps(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
SLAPI_ATTR_ENTRYUSN, bvals);
- *mods = slapi_mods_get_ldapmods_byref(&smods);
+ *mods = slapi_mods_get_ldapmods_passout(&smods);
slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
"<-- _usn_mod_next_usn\n");
13 years, 7 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/util.c | 46 ++++++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 16 deletions(-)
New commits:
commit 34c0dfe8e862d86591823004150e777b1e035b6e
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Sep 2 14:15:09 2010 -0700
Bug 629710 - escape_string does not check '\<HEX><HEX>'
https://bugzilla.redhat.com/show_bug.cgi?id=629710
Resolves: 629710
Description: do_escape_string (core of escape_string) converts
'\\ (backslash)' to '\5C' even if the following 2 characters are
hex digits. That is, the character is already escaped. This
patch checks the case and if it is, it does not escape it further.
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index c4397c7..37c6624 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -73,19 +73,23 @@
static int special_np(unsigned char c)
{
- if(c < 32 || c > 126) {
- return UTIL_ESCAPE_HEX;
- } else if ((c== '"') || (c=='\\'))
- {
- return UTIL_ESCAPE_HEX;
- }
+ if (c == '\\') {
+ return UTIL_ESCAPE_BACKSLASH;
+ }
+ if (c < 32 || c > 126 || c == '"') {
+ return UTIL_ESCAPE_HEX;
+ }
return UTIL_ESCAPE_NONE;
}
static int special_np_and_punct(unsigned char c)
{
- if (c < 32 || c > 126 || c == '*') return UTIL_ESCAPE_HEX;
- if (c == '\\' || c == '"') return UTIL_ESCAPE_BACKSLASH;
+ if (c == '\\') {
+ return UTIL_ESCAPE_BACKSLASH;
+ }
+ if (c < 32 || c > 126 || c == '"' || c == '*') {
+ return UTIL_ESCAPE_HEX;
+ }
return UTIL_ESCAPE_NONE;
}
@@ -142,16 +146,26 @@ do_escape_string (
break;
}
do {
- *bufNext++ = '\\'; --bufSpace;
- if (bufSpace < 2) {
- memcpy (bufNext, "..", 2);
- bufNext += 2;
- goto bail;
- }
if (esc == UTIL_ESCAPE_BACKSLASH) {
- *bufNext++ = *s; --bufSpace;
+ /* *s is '\\' */
+ /* If *(s+1) and *(s+2) are both hex digits,
+ * the char is already escaped. */
+ if (isxdigit(*(s+1)) && isxdigit(*(s+2))) {
+ memcpy(bufNext, s, 3);
+ bufNext += 3;
+ bufSpace -= 3;
+ s += 2;
+ } else {
+ *bufNext++ = *s; --bufSpace;
+ }
} else { /* UTIL_ESCAPE_HEX */
- sprintf (bufNext, "%02x", (unsigned)*(unsigned char*)s);
+ *bufNext++ = '\\'; --bufSpace;
+ if (bufSpace < 3) {
+ memcpy(bufNext, "..", 2);
+ bufNext += 2;
+ goto bail;
+ }
+ PR_snprintf(bufNext, 3, "%02x", *(unsigned char*)s);
bufNext += 2; bufSpace -= 2;
}
} while (++s <= last &&
13 years, 7 months